[from now] 2012/09/26 23:12:38

diff --git a/src/common.c b/src/common.c
index 554386b..f2c1c4f 100644
--- a/src/common.c
+++ b/src/common.c
@@ -45,6 +45,23 @@ int ml_table_size(lookup_info* table) {
   return table[0].value;
 }

+void* ml_generic_lookup(generic_lookup_info *table, int key) {
+  if (table == NULL) {
+    return NULL;
+  }
+  int length = table[0].key;
+
+  for (int i = 1; i <= length; ++i) {
+    if (key == table[i].key) {
+      return table[i].value;
+    }
+  }
+
+  /* not found */
+  return NULL;
+}
+
+
 /*****************************************************/

 value head(value list) {
diff --git a/src/common.h b/src/common.h
index 40ca688..f60a6bf 100644
--- a/src/common.h
+++ b/src/common.h
@@ -10,6 +10,11 @@ typedef struct lookup_info {
   int value;
 } lookup_info;

+typedef struct generic_lookup_info {
+  int key;
+  void* value;
+} generic_lookup_info;
+
 /**
  * lookup from key of OCaml to value of C, or from value of C to key OCaml
  * To be able to receive table is constructed that first is key equal zero and
@@ -19,6 +24,17 @@ int ml_lookup_to_c(lookup_info *table, value key);
 value ml_lookup_from_c(lookup_info *table, int value);
 int ml_table_size(lookup_info *table);

+/* privide to look up data from table of associating key with generic data
+   (void*).
+   It only look up by key of int, but to be useful.
+   If key can't look up from given table, return NULL.
+
+   Noted: format of table is similer to table used with lookup_info,
+          but first element of table is difference.
+          It is must to be {number of table element, 0}.
+ */
+void* ml_generic_lookup(generic_lookup_info* table, int key);
+
 /** list operation helper used from C */
 value head(value list);
 value tail(value list);
diff --git a/src/sdl_event.ml b/src/sdl_event.ml
index 1ae530c..95fa7df 100644
--- a/src/sdl_event.ml
+++ b/src/sdl_event.ml
@@ -141,6 +141,17 @@ type event =
 | Syswm of sys_wm_event

 (**
+   Push some Event Structure onto the event queue.
+
+   If can't push onto 'the event queue any reason, raise {!Sdl_event_exception} with
+   result of {b SDL_GetError()}.
+
+   @param event wish event to push
+   @raise Sdl_event_exception if event can't push onto the event queue
+*)
+external push_event: event -> unit = "sdlcaml_push_event"
+
+(**
  * Pump the event loop, gathering events from the input devices.
  * Often call the need for this function is hidden from the user what
  * since {!poll_event} or {!wait_event} implicitly calls this function.
diff --git a/src/sdl_event_convert.c b/src/sdl_event_convert.c
new file mode 100644
index 0000000..05d6473
--- /dev/null
+++ b/src/sdl_event_convert.c
@@ -0,0 +1,571 @@
+#include <SDL.h>
+
+#include <caml/mlvalues.h>
+#include <caml/memory.h>
+#include <caml/alloc.h>
+#include <caml/fail.h>
+#include "common.h"
+#include "sdl_generic.h"
+#include "sdl_key_trans.h"
+#include "sdl_input_trans.h"
+#include "sdl_event_trans.h"
+#include "sdl_event_convert.h"
+
+value caml_convert_c2m_active_event(SDL_Event* event, value tag) {
+  CAMLparam1(tag);
+  CAMLlocal2(event_tag, active);
+  event_tag     = caml_alloc(1, Int_val(tag));
+  active        = caml_alloc(2, 0);
+
+  Store_field(active, 0, event->active.gain == 1 ? Val_true : Val_false);
+  switch (event->active.state) {
+    case SDL_APPMOUSEFOCUS: Store_field(active, 1, Val_int(0)); break;
+    case SDL_APPINPUTFOCUS: Store_field(active, 1, Val_int(1)); break;
+    case SDL_APPACTIVE: Store_field(active, 1, Val_int(2)); break;
+    default: caml_invalid_argument("invalid state in SDL_ACTIVEEVENT");
+  }
+
+  Store_field(event_tag, 0, active);
+  CAMLreturn(event_tag);
+}
+
+value caml_convert_c2m_keyboard_event(SDL_Event* event, value tag) {
+  CAMLparam1(tag);
+  CAMLlocal4(event_tag, keyboard, keyinfo, modkey);
+  event_tag = caml_alloc(1, Int_val(tag));
+  keyboard  = caml_alloc(1, 0);
+  keyinfo   = caml_alloc(2, 0);
+  modkey    = Val_emptylist;
+
+  /* set data of keysym  */
+  Store_field(keyinfo, 0, ml_lookup_from_c(ml_symkey_trans_table,
+                                           event->key.keysym.sym));
+
+  /* get current state of the modify keys including pressed now only */
+  for (int i = ml_table_size(ml_modkey_trans_table); i > 0; --i) {
+    if (event->key.keysym.mod & ml_modkey_trans_table[i].value) {
+      modkey = add_head(modkey, Val_int(ml_modkey_trans_table[i].key));
+    }
+  }
+  Store_field(keyinfo, 1, modkey);
+
+  Store_field(keyboard, 0, keyinfo);
+  Store_field(event_tag, 0, keyboard);
+
+  CAMLreturn(event_tag);
+}
+
+value caml_convert_c2m_mousemotion_event(SDL_Event* event, value tag) {
+  CAMLparam1(tag);
+  CAMLlocal3(event_tag, motion, button);
+  event_tag     = caml_alloc(1, Int_val(tag));
+  motion        = caml_alloc(5, 0);
+  button        = Val_emptylist;
+
+  const int MAX_BUTTON = 32;
+
+  Store_field(motion, 0, Val_int(event->motion.x));
+  Store_field(motion, 1, Val_int(event->motion.y));
+  Store_field(motion, 2, Val_int(event->motion.xrel));
+  Store_field(motion, 3, Val_int(event->motion.yrel));
+
+  /* get mouse state of as many as possible buttons */
+  for (int i = MAX_BUTTON; i > 0; --i) {
+    CAMLlocal1(state);
+    state = caml_alloc(2, 0);
+    Store_field(state, 0, Val_int(i));
+    Store_field(state, 1, ml_lookup_from_c(ml_generic_button_table,
+                                           event->motion.state & SDL_BUTTON(i)));
+
+    button = add_head(button, state);
+  }
+  Store_field(motion, 4, button);
+
+  Store_field(event_tag, 0, motion);
+
+  CAMLreturn(event_tag);
+}
+
+value caml_convert_c2m_mousebutton_event(SDL_Event* event, value tag) {
+  CAMLparam1(tag);
+  CAMLlocal3(event_tag, statelist, button);
+  event_tag = caml_alloc(1, Int_val(tag));
+  statelist = caml_alloc(3, 0);
+  button    = Val_emptylist;
+
+  const int                              MAX_BUTTON = 32;
+  int                                    button_states[MAX_BUTTON];
+  memset(button_states, 0, sizeof(int) * MAX_BUTTON);
+
+  Store_field(statelist, 0, Val_int(event->button.x));
+  Store_field(statelist, 1, Val_int(event->button.y));
+
+  /* get mouse state of as many as possible buttons */
+  for (int i = MAX_BUTTON; i > 0; --i) {
+    CAMLlocal1(state);
+    state = caml_alloc(2, 0);
+    Store_field(state, 0, Val_int(i));
+    Store_field(state, 1, ml_lookup_from_c(ml_generic_button_table,
+                                           event->button.state & SDL_BUTTON(i)));
+
+    button = add_head(button, state);
+  }
+  Store_field(statelist, 2, button);
+
+  Store_field(event_tag, 0, statelist);
+
+  CAMLreturn(event_tag);
+}
+
+value caml_convert_c2m_joyaxismotion_event(SDL_Event* event, value tag) {
+  CAMLparam1(tag);
+  CAMLlocal2(event_tag, axis);
+  event_tag  = caml_alloc(1, Int_val(tag));
+  axis = caml_alloc(3, 0);
+
+  Store_field(axis, 0, Val_int(event->jaxis.which));
+  Store_field(axis, 1, Val_int(event->jaxis.axis));
+  Store_field(axis, 2, Val_int(event->jaxis.value));
+
+  Store_field(event_tag, 0, axis);
+
+  CAMLreturn(event_tag);
+}
+
+value caml_convert_c2m_joyballmotion_event(SDL_Event* event, value tag) {
+  CAMLparam1(tag);
+  CAMLlocal2(event_tag, ball);
+  event_tag = caml_alloc(1, Int_val(tag));
+  ball      = caml_alloc(4, 0);
+
+  Store_field(ball, 0, Val_int(event->jball.which));
+  Store_field(ball, 1, Val_int(event->jball.ball));
+  Store_field(ball, 2, Val_int(event->jball.xrel));
+  Store_field(ball, 3, Val_int(event->jball.yrel));
+
+  Store_field(event_tag, 0, ball);
+
+  CAMLreturn(event_tag);
+}
+
+value caml_convert_c2m_joyhatmotion_event(SDL_Event* event, value tag) {
+  CAMLparam0();
+  CAMLlocal3(event_tag, hat, switchlist);
+  event_tag  = caml_alloc(1, Int_val(tag));
+  hat        = caml_alloc(3, 0);
+  switchlist = Val_emptylist;
+  int state  = event->jhat.value;
+
+  Store_field(hat, 0, Val_int(event->jhat.which));
+  Store_field(hat, 1, Val_int(event->jhat.hat));
+
+  /* check all hat position in current state, but list contains
+     only bit masking result of 1.
+   */
+  for (int i = ml_table_size(ml_joyhat_trans_table); i > 0; --i) {
+    if (state & ml_joyhat_trans_table[i].value) {
+      switchlist = add_head(switchlist, Val_int(ml_joyhat_trans_table[i].key));
+    }
+  }
+  Store_field(hat, 2, switchlist);
+
+  Store_field(event_tag, 0, hat);
+
+  CAMLreturn(event_tag);
+}
+
+value caml_convert_c2m_joybutton_event(SDL_Event* event, value tag) {
+  CAMLparam0();
+  CAMLlocal2(event_tag, button);
+  event_tag = caml_alloc(1, Int_val(tag));
+  button    = caml_alloc(2, 0);
+
+  Store_field(button, 0, Val_int(event->jbutton.which));
+  Store_field(button, 1, Val_int(event->jbutton.button));
+
+  Store_field(event_tag, 0, button);
+
+  CAMLreturn(event_tag);
+}
+
+value caml_convert_c2m_resize_event(SDL_Event* event, value tag) {
+  CAMLparam0();
+  CAMLlocal2(event_tag, resize);
+  event_tag = caml_alloc(1, Int_val(tag));
+  resize    = caml_alloc(2, 0);
+
+  Store_field(resize, 0, Val_int(event->resize.w));
+  Store_field(resize, 1, Val_int(event->resize.h));
+
+  Store_field(event_tag, 0, resize);
+
+  CAMLreturn(event_tag);
+}
+
+value caml_convert_c2m_expose_event(SDL_Event* event, value tag) {
+  CAMLparam1(tag);
+  CAMLreturn(tag);
+}
+
+value caml_convert_c2m_quit_event(SDL_Event* event, value tag) {
+  CAMLparam1(tag);
+  CAMLreturn(tag);
+}
+
+value caml_convert_c2m_user_event(SDL_Event* event, value tag) {
+  /* TODO: I have to implement somehow */
+  CAMLparam1(tag);
+  CAMLreturn(tag);
+}
+
+value caml_convert_c2m_syswm_event(SDL_Event* event, value tag) {
+  /* TODO: I decide to implement or not. */
+  CAMLparam1(tag);
+  CAMLreturn(tag);
+}
+
+typedef value (*convert_c2m)(SDL_Event*, value);
+/* indexed MLTAG_* value in sdl_event_trans.h */
+generic_lookup_info conversion_c2m_funcs[] = {
+  {16, 0},
+  {MLTAG_ACTIVE      , caml_convert_c2m_active_event        },
+  {MLTAG_KEYDOWN     , caml_convert_c2m_keyboard_event      },
+  {MLTAG_KEYUP       , caml_convert_c2m_keyboard_event      },
+  {MLTAG_MOTION      , caml_convert_c2m_mousemotion_event   },
+  {MLTAG_BUTTONDOWN  , caml_convert_c2m_mousebutton_event   },
+  {MLTAG_BUTTONUP    , caml_convert_c2m_mousebutton_event   },
+  {MLTAG_JAXIS       , caml_convert_c2m_joyaxismotion_event },
+  {MLTAG_JBALL       , caml_convert_c2m_joyballmotion_event },
+  {MLTAG_JHAT        , caml_convert_c2m_joyhatmotion_event  },
+  {MLTAG_JBUTTONDOWN , caml_convert_c2m_joybutton_event     },
+  {MLTAG_JBUTTONUP   , caml_convert_c2m_joybutton_event     },
+  {MLTAG_RESIZE      , caml_convert_c2m_resize_event        },
+  {MLTAG_EXPOSE      , caml_convert_c2m_expose_event        },
+  {MLTAG_QUIT        , caml_convert_c2m_quit_event          },
+  {MLTAG_USER        , caml_convert_c2m_user_event          },
+  {MLTAG_SYSWM       , caml_convert_c2m_syswm_event         },
+};
+
+/* create and return Event Structure for OCaml */
+value caml_convert_event_c2m(SDL_Event *event) {
+  if (event == NULL) {
+    caml_invalid_argument("invalid event received : caml_convert_event_c2m");
+  }
+
+  /* this type is value of MLTAG_* in sdl_event_trans.h.
+     Nevertheless, this function switching is based on MLTAG_* value,
+     I think bad of it...
+   */
+  value type = ml_lookup_from_c(ml_event_tag_table, event->type);
+  convert_c2m func = (convert_c2m)ml_generic_lookup(conversion_c2m_funcs,
+                                                    Int_val(type));
+  CAMLreturn((*func)(event, type))
+}
+
+/*******************************************************************/
+/* convert event to SDL_Event */
+
+SDL_Event* caml_convert_m2c_active_event(value ml_event) {
+  CAMLparam1(ml_event);
+  SDL_Event* e = malloc(sizeof(SDL_Event));
+  e->type = SDL_ACTIVEEVENT;
+  e->active.gain = Int_val(Field(ml_event, 0));
+
+  switch (Int_val(Field(ml_event, 1))) {
+    case 0: e->active.state = SDL_APPMOUSEFOCUS; break;
+    case 1: e->active.state = SDL_APPINPUTFOCUS; break;
+    case 2: e->active.state = SDL_APPACTIVE; break;
+  }
+
+  CAMLnoreturn;
+  return e;
+}
+
+SDL_Event* caml_convert_m2c_keyup_event(value ml_event) {
+  CAMLparam1(ml_event);
+  SDL_Event* e = malloc(sizeof(SDL_Event));
+  e->type = SDL_KEYUP;
+  e->key.state = SDL_RELEASED;
+
+  value synonym = Field(Field(ml_event, 0), 0);
+  e->key.keysym.sym = ml_lookup_to_c(ml_symkey_trans_table, synonym);
+  e->key.keysym.mod = KMOD_NONE;
+
+  value mod_list = Field(Field(ml_event, 0), 1);
+  while (is_not_nil(mod_list)) {
+    e->key.keysym.mod |= ml_lookup_to_c(ml_modkey_trans_table,
+                                        head(mod_list));
+    mod_list = tail(mod_list);
+  }
+
+  CAMLnoreturn;
+  return e;
+}
+
+SDL_Event* caml_convert_m2c_keydown_event(value ml_event) {
+  CAMLparam1(ml_event);
+  SDL_Event* e = malloc(sizeof(SDL_Event));
+  e->type = SDL_KEYDOWN;
+  e->key.state = SDL_PRESSED;
+
+  value synonym = Field(Field(ml_event, 0), 0);
+  e->key.keysym.sym = ml_lookup_to_c(ml_symkey_trans_table, synonym);
+  e->key.keysym.mod = KMOD_NONE;
+
+  value mod_list = Field(Field(ml_event, 0), 1);
+  while (is_not_nil(mod_list)) {
+    e->key.keysym.mod |= ml_lookup_to_c(ml_modkey_trans_table,
+                                        head(mod_list));
+    mod_list = tail(mod_list);
+  }
+
+  CAMLnoreturn;
+  return e;
+}
+
+SDL_Event* caml_convert_m2c_mousemotion_event(value ml_event) {
+  CAMLparam1(ml_event);
+  SDL_Event* e = malloc(0, sizeof(SDL_Event));
+  e->type = SDL_MOUSEMOTION;
+
+  const int MAX_BUTTON = 32;
+
+  event->motion.x = Int_val(Field(ml_event, 0));
+  event->motion.y = Int_val(Field(ml_event, 1));
+  event->motion.xrel = Int_val(Field(ml_event, 2));
+  event->motion.yrel = Int_val(Field(ml_event, 3));
+
+  value button_state = Field(ml_event, 4);
+  while (is_not_nil(button_state)) {
+    CAMLlocal1(hd);
+    hd = head(button_state);
+    int num = Int_val(hd, 0);
+    int state = ml_lookup_to_c(ml_generic_button_table, Field(hd, 1));
+
+    if (num >= MAX_BUTTON || num < 1) {
+      /* do nothing */
+    } else if (state) {
+      e->motion.state |= SDL_BUTTON(num);
+    } else {
+      e->motion.state &= !SDL_BUTTON(num);
+    }
+
+    button_state = tail(button_state);
+  }
+
+  CAMLnoreturn;
+  return e;
+}
+
+SDL_Event* caml_convert_m2c_mousebuttonup_event(value ml_event) {
+  CAMLparam1(ml_event);
+  SDL_Event* e = malloc(sizeof(SDL_Event));
+  e->type = SDL_MOUSEBUTTONUP;
+  e->button.x = Int_val(Field(ml_event, 0));
+  e->button.y = Int_val(Field(ml_event, 1));
+
+  /* Restore mouse button state from OCaml value.
+     If given over button of number of 32, be ignored it.
+   */
+  const int MAX_BUTTON   = 32;
+  value     button_state = Field(ml_event, 2);
+
+  while (is_not_nil(button_state)) {
+    CAMLlocal1(hd);
+    hd = head(button_state);
+    int num = Int_val(hd, 0);
+    int state = ml_lookup_to_c(ml_generic_button_table, Field(hd, 1));
+
+    if (num >= MAX_BUTTON || num < 1) {
+      /* do nothing */
+    } else if (state) {
+      /* up is mouse button released, so mouse state reflect at the button */
+      e->button.state &= !SDL_BUTTON(num);
+    }
+    button_state = tail(button_state);
+  }
+
+  CAMLnoreturn;
+  return e;
+}
+
+SDL_Event* caml_convert_m2c_mousebuttondown_event(value ml_event) {
+  CAMLparam1(ml_event);
+  SDL_Event* e = malloc(sizeof(SDL_Event));
+  e->type = SDL_MOUSEBUTTONDOWN;
+  e->button.x = Int_val(Field(ml_event, 0));
+  e->button.y = Int_val(Field(ml_event, 1));
+
+  /* Restore mouse button state from OCaml value.
+     If given over button of number of 32, be ignored it.
+   */
+  const int MAX_BUTTON   = 32;
+  value     button_state = Field(ml_event, 2);
+
+  while (is_not_nil(button_state)) {
+    CAMLlocal1(hd);
+    hd = head(button_state);
+    int num = Int_val(hd, 0);
+    int state = ml_lookup_to_c(ml_generic_button_table, Field(hd, 1));
+
+    if (num >= MAX_BUTTON || num < 1) {
+      /* do nothing */
+    } else if (state) {
+      e->button.state |= SDL_BUTTON(num);
+    }
+    button_state = tail(button_state);
+  }
+
+  CAMLnoreturn;
+  return e;
+}
+
+SDL_Event* caml_convert_m2c_joyaxismotion_event(value ml_event) {
+  CAMLparam1(ml_event);
+  SDL_Event* e = malloc(sizeof(SDL_Event));
+  e->type = SDL_JOYAXISMOTION;
+
+  event->jaxis.which = Int_val(Field(ml_event, 0));
+  event->jaxis.axis  = Int_val(Field(ml_event, 1));
+  event->jaxis.value = Int_val(Field(ml_event, 2));
+
+  CAMLnoreturn;
+  return e;
+}
+
+SDL_Event* caml_convert_m2c_joyballmotion_event(value ml_event) {
+  CAMLparam1(ml_event);
+  SDL_Event* e = malloc(sizeof(SDL_Event));
+  e->type = SDL_JOYBALLMOTION;
+
+  e->jball.which = Int_val(Field(ml_event, 0));
+  e->jball.ball  = Int_val(Field(ml_event, 1));
+  e->jball.xrel  = Int_val(Field(ml_event, 2));
+  e->jball.yrel  = Int_val(Field(ml_event, 3));
+
+  CAMLnoreturn;
+  return e;
+}
+
+SDL_Event* caml_convert_m2c_joyhatmotion_event(value ml_event) {
+  CAMLparam1(ml_event);
+  int state  = event->jhat.value;
+  SDL_Event* e = malloc(sizeof(SDL_Event));
+  e->type = SDL_JHATBUTTON;
+  e->jhat.which = Int_val(Field(ml_event, 0));
+  e->jhat.hat = Int_val(Field(ml_event, 1));
+
+  Uint8 hatbutton_value = 0;
+
+  /* restore hat switch value from OCaml value */
+  value hatbutton = Field(ml_event, 2);
+  while (is_not_nil(hatbutton)) {
+    hatbutton_value &= ml_lookup_to_c(head(hatbutton));
+    hatbutton = tail(list);
+  }
+
+  e->jhat.value = hatbutton_value;
+  CAMLnoreturn;
+  return e;
+}
+
+/* TODO: integrate jbuttondown/up function some day... */
+SDL_Event* caml_convert_m2c_jbuttondown_event(value ml_event) {
+  CAMLparam1(ml_event);
+  SDL_Event* e = malloc(sizeof(SDL_Event));
+  e->type = SDL_JOYBUTTONDOWN;
+
+  e->jbutton.which = Int_val(Field(ml_event, 0));
+  e->jbutton.button = Int_val(Field(ml_event, 1));
+  CAMLnoreturn;
+  return e;
+}
+
+SDL_Event* caml_convert_m2c_jbuttonup_event(value ml_event) {
+  CAMLparam1(ml_event);
+  SDL_Event* e = malloc(sizeof(SDL_Event));
+  e->type = SDL_JOYBUTTONUP;
+
+  e->jbutton.which = Int_val(Field(ml_event, 0));
+  e->jbutton.button = Int_val(Field(ml_event, 1));
+  CAMLnoreturn;
+  return e;
+}
+
+SDL_Event* caml_convert_m2c_resize_event(value ml_event) {
+  CAMLparam1(ml_event);
+  SDL_Event* e = malloc(sizeof(SDL_Event));
+  e->type = SDL_VIDEORESIZE;
+
+  e->resize.w = Int_val(Field(ml_event, 0));
+  e->resize.h = Int_val(Field(ml_event, 1));
+  CAMLnoreturn;
+  return e;
+}
+
+SDL_Event* caml_convert_m2c_expose_event(value ml_event) {
+  CAMLparam1(ml_event);
+  SDL_Event* e = malloc(sizeof(SDL_Event));
+  e->type = SDL_VIDEOEXPOSE;
+  CAMLnoreturn;
+  return e;
+}
+
+SDL_Event* caml_convert_m2c_quit_event(value ml_event) {
+  CAMLparam1(ml_event);
+  SDL_Event* e = malloc(sizeof(SDL_Event));
+  e->type = SDL_QUIT;
+  CAMLnoreturn;
+  return e;
+}
+
+SDL_Event* caml_convert_m2c_user_event(value ml_event) {
+  /* TODO: I have to implement somehow */
+  CAMLparam1(ml_event);
+  SDL_Event* e = malloc(sizeof(SDL_Event));
+  e->type = SDL_USEREVENT;
+  CAMLnoreturn;
+  return e;
+}
+
+SDL_Event* caml_convert_m2c_syswm_event(value ml_event) {
+  /* TODO: I decide to implement or not. */
+  CAMLparam1(ml_event);
+  SDL_Event* e = malloc(sizeof(SDL_Event));
+  e->type = SDL_SYSWMEVENT;
+  CAMLnoreturn;
+  return e;
+}
+
+SDL_Event* caml_convert_event_m2c(value ml_event) {
+  CAMLparam1(ml_event);
+  SDL_Event* event = NULL;
+
+  if (Is_long(ml_event)) {
+    switch (Int_val(ml_event)) {
+      case MLTAG_EXPOSE: event = caml_convert_m2c_expose_event(ml_event); break;
+      case MLTAG_QUIT: event   = caml_convert_m2c_quit_event(ml_event); break;
+    }
+  } else {
+    value e_struct = Field(ml_event, 1);
+    switch (Tag_val(ml_event)) {
+      case MLTAG_ACTIVE: event      = caml_convert_m2c_active_event(e_struct); break;
+      case MLTAG_KEYDOWN: event     = caml_convert_m2c_keydown_event(e_struct); break;
+      case MLTAG_KEYUP: event       = caml_convert_m2c_keyup_event(e_struct); break;
+      case MLTAG_MOTION: event      = caml_convert_m2c_mousemotion_event(e_struct); break;
+      case MLTAG_BUTTONDOWN: event  = caml_convert_m2c_buttondown_event(e_struct); break;
+      case MLTAG_BUTTONUP: event    = caml_convert_m2c_buttonup_event(e_struct); break;
+      case MLTAG_JAXIS: event       = caml_convert_m2c_jaxis_event(e_struct); break;
+      case MLTAG_JBALL: event       = caml_convert_m2c_jball_event(e_struct); break;
+      case MLTAG_JHAT: event        = caml_convert_m2c_jhat_event(e_struct); break;
+      case MLTAG_JBUTTONDOWN: event = caml_convert_m2c_jbuttondown_event(e_struct); break;
+      case MLTAG_JBUTTONUP: event   = caml_convert_m2c_jbuttonup_event(e_struct); break;
+      case MLTAG_RESIZE: event      = caml_convert_m2c_resize_event(e_struct); break;
+      case MLTAG_USER: event        = caml_convert_m2c_user_event(e_struct); break;
+      case MLTAG_SYSWM: event       = caml_convert_m2c_syswm_event(e_struct); break;
+    }
+  }
+
+  CAMLnoreturn;
+  return event;
+}
diff --git a/src/sdl_event_convert.h b/src/sdl_event_convert.h
new file mode 100644
index 0000000..8923ac0
--- /dev/null
+++ b/src/sdl_event_convert.h
@@ -0,0 +1,15 @@
+#ifndef __SDL_EVENT_CONVERT_H__
+#define __SDL_EVENT_CONVERT_H__
+
+#include <caml/mlvalues.h>
+#include <SDL.h>
+
+/** convert ml to C or C to ml. */
+
+/* convert received event to pointer to SDL_Event.
+   To return SDL_Event have to apply free by received.
+*/
+SDL_Event* caml_convert_event_m2c(value);
+value caml_convert_event_c2m(SDL_Event*);
+
+#endif /* __SDL_EVENT_CONVERT_H__ */
diff --git a/src/sdl_event_stub.c b/src/sdl_event_stub.c
index d8b188d..696d47a 100644
--- a/src/sdl_event_stub.c
+++ b/src/sdl_event_stub.c
@@ -6,27 +6,8 @@
 #include <caml/fail.h>
 #include "common.h"
 #include "sdl_generic.h"
-#include "sdl_key_trans.h"
-#include "sdl_input_trans.h"
-
-enum EVENTTAG {
-  ETAG_ACTIVE      = 0,
-  ETAG_KEYDOWN     = 1,
-  ETAG_KEYUP       = 2,
-  ETAG_MOTION      = 3,
-  ETAG_BUTTONDOWN  = 4,
-  ETAG_BUTTONUP    = 5,
-  ETAG_JAXIS       = 6,
-  ETAG_JBALL       = 7,
-  ETAG_JHAT        = 8,
-  ETAG_JBUTTONDOWN = 9,
-  ETAG_JBUTTONUP   = 10,
-  ETAG_RESIZE      = 11,
-  ETAG_EXPOSE      = 12,
-  ETAG_QUIT        = 13,
-  ETAG_USER        = 14,
-  ETAG_SYSWM       = 15
-};
+#include "sdl_event_trans.h"
+#include "sdl_event_convert.h"

 CAMLprim value sdlcaml_pump_events(value unit) {
   CAMLparam0();
@@ -37,249 +18,13 @@ CAMLprim value sdlcaml_pump_events(value unit) {
   return Val_unit;
 }

-value caml_create_active_event(SDL_Event* event) {
-  CAMLparam0();
-  CAMLlocal2(event_tag, active);
-  event_tag     = caml_alloc(1, ETAG_ACTIVE);
-  active        = caml_alloc(2, 0);
-
-  Store_field(active, 0, event->active.gain == 1 ? Val_true : Val_false);
-  switch (event->active.state) {
-    case SDL_APPMOUSEFOCUS: Store_field(active, 1, Val_int(0)); break;
-    case SDL_APPINPUTFOCUS: Store_field(active, 1, Val_int(1)); break;
-    case SDL_APPACTIVE: Store_field(active, 1, Val_int(2)); break;
-    default: caml_invalid_argument("invalid state in SDL_ACTIVEEVENT");
-  }
-
-  Store_field(event_tag, 0, active);
-  CAMLreturn(event_tag);
-}
-
-value caml_create_keyboard_event(SDL_Event* event, int tag) {
-  CAMLparam0();
-  CAMLlocal4(event_tag, keyboard, keyinfo, modkey);
-  event_tag = caml_alloc(1, tag);
-  keyboard  = caml_alloc(1, 0);
-  keyinfo   = caml_alloc(2, 0);
-  modkey    = Val_emptylist;
-
-  /* set data of keysym  */
-  Store_field(keyinfo, 0, ml_lookup_from_c(ml_symkey_trans_table,
-                                           event->key.keysym.sym));
-
-  /* get current state of the modify keys including pressed now only */
-  for (int i = ml_table_size(ml_modkey_trans_table); i > 0; --i) {
-    if (event->key.keysym.mod & ml_modkey_trans_table[i].value) {
-      modkey = add_head(modkey, Val_int(ml_modkey_trans_table[i].key));
-    }
-  }
-  Store_field(keyinfo, 1, modkey);
-
-  Store_field(keyboard, 0, keyinfo);
-  Store_field(event_tag, 0, keyboard);
-
-  CAMLreturn(event_tag);
-}
-
-value caml_create_mousemotion_event(SDL_Event* event) {
-  CAMLparam0();
-  CAMLlocal3(event_tag, motion, button);
-  event_tag     = caml_alloc(1, ETAG_MOTION);
-  motion        = caml_alloc(5, 0);
-  button        = Val_emptylist;
-
-  const int MAX_BUTTON = 32;
-  int       button_states[MAX_BUTTON];
-
-  memset(button_states, 0, sizeof(int) * MAX_BUTTON);
-
-  Store_field(motion, 0, Val_int(event->motion.x));
-  Store_field(motion, 1, Val_int(event->motion.y));
-  Store_field(motion, 2, Val_int(event->motion.xrel));
-  Store_field(motion, 3, Val_int(event->motion.yrel));
-
-  /* get mouse state of as many as possible buttons */
-  for (int i = MAX_BUTTON; i > 0; --i) {
-    CAMLlocal1(state);
-    state = caml_alloc(2, 0);
-    Store_field(state, 0, Val_int(i));
-    Store_field(state, 1, ml_lookup_from_c(ml_generic_button_table,
-                                           event->motion.state & SDL_BUTTON(i)));
-
-    button = add_head(button, state);
-  }
-  Store_field(motion, 4, button);
-
-  Store_field(event_tag, 0, motion);
-
-  CAMLreturn(event_tag);
-}
-
-value caml_create_mousebutton_event(SDL_Event* event, int tag) {
-  CAMLparam0();
-  CAMLlocal3(event_tag, statelist, button);
-  event_tag = caml_alloc(1, tag);
-  statelist = caml_alloc(3, 0);
-  button    = Val_emptylist;
-
-  const int                              MAX_BUTTON = 32;
-  int                                    button_states[MAX_BUTTON];
-  memset(button_states, 0, sizeof(int) * MAX_BUTTON);
-
-  Store_field(statelist, 0, Val_int(event->button.x));
-  Store_field(statelist, 1, Val_int(event->button.y));
-
-  /* get mouse state of as many as possible buttons */
-  for (int i = MAX_BUTTON; i > 0; --i) {
-    CAMLlocal1(state);
-    state = caml_alloc(2, 0);
-    Store_field(state, 0, Val_int(i));
-    Store_field(state, 1, ml_lookup_from_c(ml_generic_button_table,
-                                           event->button.state & SDL_BUTTON(i)));
-
-    button = add_head(button, state);
-  }
-  Store_field(statelist, 2, button);
-
-  Store_field(event_tag, 0, statelist);
-
-  CAMLreturn(event_tag);
-}
-
-value caml_create_joyaxismotion_event(SDL_Event* event) {
-  CAMLparam0();
-  CAMLlocal2(event_tag, axis);
-  event_tag  = caml_alloc(1, ETAG_JAXIS);
-  axis = caml_alloc(3, 0);
-
-  Store_field(axis, 0, Val_int(event->jaxis.which));
-  Store_field(axis, 1, Val_int(event->jaxis.axis));
-  Store_field(axis, 2, Val_int(event->jaxis.value));
-
-  Store_field(event_tag, 0, axis);
-
-  CAMLreturn(event_tag);
-}
-
-value caml_create_joyballmotion_event(SDL_Event* event) {
-  CAMLparam0();
-  CAMLlocal2(event_tag, ball);
-  event_tag = caml_alloc(1, ETAG_JBALL);
-  ball      = caml_alloc(4, 0);
-
-  Store_field(ball, 0, Val_int(event->jball.which));
-  Store_field(ball, 1, Val_int(event->jball.ball));
-  Store_field(ball, 2, Val_int(event->jball.xrel));
-  Store_field(ball, 3, Val_int(event->jball.yrel));
-
-  Store_field(event_tag, 0, ball);
-
-  CAMLreturn(event_tag);
-}
-
-value caml_create_joyhatmotion_event(SDL_Event* event) {
-  CAMLparam0();
-  CAMLlocal3(event_tag, hat, switchlist);
-  event_tag  = caml_alloc(1, ETAG_JHAT);
-  hat        = caml_alloc(3, 0);
-  switchlist = Val_emptylist;
-  int state  = event->jhat.value;
-
-  Store_field(hat, 0, Val_int(event->jhat.which));
-  Store_field(hat, 1, Val_int(event->jhat.hat));
-
-  /* check all hat position in current state, but list contains
-     only bit masking result of 1.
-   */
-  for (int i = ml_table_size(ml_joyhat_trans_table); i > 0; --i) {
-    if (state & ml_joyhat_trans_table[i].value) {
-      switchlist = add_head(switchlist, Val_int(ml_joyhat_trans_table[i].key));
-    }
-  }
-  Store_field(hat, 2, switchlist);
-
-  Store_field(event_tag, 0, hat);
-
-  CAMLreturn(event_tag);
-}
-
-value caml_create_joybutton_event(SDL_Event* event, int tag) {
-  CAMLparam0();
-  CAMLlocal2(event_tag, button);
-  event_tag = caml_alloc(1, tag);
-  button    = caml_alloc(2, 0);
-
-  Store_field(button, 0, Val_int(event->jbutton.which));
-  Store_field(button, 1, Val_int(event->jbutton.button));
-
-  Store_field(event_tag, 0, button);
-
-  CAMLreturn(event_tag);
-}
-
-value caml_create_resize_event(SDL_Event* event) {
-  CAMLparam0();
-  CAMLlocal2(event_tag, resize);
-  event_tag = caml_alloc(1, ETAG_RESIZE);
-  resize    = caml_alloc(2, 0);
-
-  Store_field(resize, 0, Val_int(event->resize.w));
-  Store_field(resize, 1, Val_int(event->resize.h));
-
-  Store_field(event_tag, 0, resize);
-
-  CAMLreturn(event_tag);
-}
-
-value caml_create_expose_event(SDL_Event* event) {
-  return Val_int(ETAG_EXPOSE);
-}
-
-value caml_create_quit_event(SDL_Event* event) {
-  return Val_int(ETAG_QUIT);
-}
-
-value caml_create_user_event(SDL_Event* event) {
-  /* TODO: I have to implement somehow */
-  return Val_int(ETAG_USER);
-}
-
-value caml_create_syswm_event(SDL_Event* event) {
-  /* TODO: I decide to implement or not. */
-  return Val_int(ETAG_SYSWM);
-}
-
-/* create and return Event Structure for OCaml */
-value caml_create_event_struct(SDL_Event *event) {
-  switch (event->type) {
-    case SDL_ACTIVEEVENT:     return caml_create_active_event(event);
-    case SDL_KEYDOWN:         return caml_create_keyboard_event(event, ETAG_KEYDOWN);
-    case SDL_KEYUP:           return caml_create_keyboard_event(event, ETAG_KEYUP);
-    case SDL_MOUSEMOTION:     return caml_create_mousemotion_event(event);
-    case SDL_MOUSEBUTTONDOWN: return caml_create_mousebutton_event(event, ETAG_BUTTONDOWN);
-    case SDL_MOUSEBUTTONUP:   return caml_create_mousebutton_event(event, ETAG_BUTTONUP);
-    case SDL_JOYAXISMOTION:   return caml_create_joyaxismotion_event(event);
-    case SDL_JOYBALLMOTION:   return caml_create_joyballmotion_event(event);
-    case SDL_JOYHATMOTION:    return caml_create_joyhatmotion_event(event);
-    case SDL_JOYBUTTONDOWN:   return caml_create_joybutton_event(event, ETAG_JBUTTONDOWN);
-    case SDL_JOYBUTTONUP:     return caml_create_joybutton_event(event, ETAG_JBUTTONUP);
-    case SDL_VIDEORESIZE:     return caml_create_resize_event(event);
-    case SDL_VIDEOEXPOSE:     return caml_create_expose_event(event);
-    case SDL_QUIT:            return caml_create_quit_event(event);
-    case SDL_USEREVENT:       return caml_create_user_event(event);
-    case SDL_SYSWMEVENT:      return caml_create_syswm_event(event);
-    default:
-      caml_invalid_argument("unrecognized event type!");
-  }
-}
-
 CAMLprim value sdlcaml_poll_event(value unit) {
   CAMLparam0();

   SDL_Event event;
   if (SDL_PollEvent(&event)) {
     CAMLlocal2(event_struct, option);
-    event_struct = caml_create_event_struct(&event);
+    event_struct = caml_convert_event_c2m(&event);

     option = caml_alloc(1,0);
     Store_field(option, 0, event_struct);
@@ -295,7 +40,7 @@ CAMLprim value sdlcaml_wait_event(value unit) {
   SDL_Event event;
   if (SDL_WaitEvent(&event)) {
     CAMLlocal2(event_struct, option);
-    event_struct = caml_create_event_struct(&event);
+    event_struct = caml_convert_event_c2m(&event);

     option = caml_alloc(1,0);
     Store_field(option, 0, event_struct);
@@ -315,26 +60,7 @@ CAMLprim value sdlcaml_event_state(value etype, value state) {
     default: caml_invalid_argument("invalid event state in sdlcaml_event_state");
   }

-  int event_type = 0;
-  switch (Int_val(etype)) {
-    case  0: event_type = SDL_ACTIVEEVENT; break;
-    case  1: event_type = SDL_KEYDOWN; break;
-    case  2: event_type = SDL_KEYUP; break;
-    case  3: event_type = SDL_MOUSEMOTION; break;
-    case  4: event_type = SDL_MOUSEBUTTONDOWN; break;
-    case  5: event_type = SDL_MOUSEBUTTONUP; break;
-    case  6: event_type = SDL_JOYAXISMOTION; break;
-    case  7: event_type = SDL_JOYBALLMOTION; break;
-    case  8: event_type = SDL_JOYHATMOTION; break;
-    case  9: event_type = SDL_JOYBUTTONDOWN; break;
-    case 10: event_type = SDL_JOYBUTTONUP; break;
-    case 11: event_type = SDL_VIDEORESIZE; break;
-    case 12: event_type = SDL_VIDEOEXPOSE; break;
-    case 13: event_type = SDL_QUIT; break;
-    case 14: event_type = SDL_USEREVENT; break;
-    case 15: event_type = SDL_SYSWMEVENT; break;
-    default: caml_invalid_argument("invalid event type in sdlcaml_event_state");
-  }
+  int event_type = ml_lookup_to_c(ml_event_tag_table, etype);

   /* responce only return if event_state is only SDL_QUERY */
   int response = SDL_EventState(event_type, event_state);
@@ -369,3 +95,24 @@ CAMLprim value sdlcaml_get_app_state(value unit) {

   CAMLreturn(current_state);
 }
+
+CAMLprim value sdlcaml_push_event(value ml_event) {
+  CAMLparam1(ml_event);
+
+  SDL_Event* event = caml_convert_event_m2c(ml_event);
+
+  if (SDL_PushEvent(event)) {
+    if (event != NULL) {
+      free(event);
+    }
+    caml_raise_with_string(caml_named_value("SDL_event_exception"),
+                           SDL_GetError());
+  }
+
+  if (event != NULL) {
+    free(event);
+  }
+
+  CAMLnoreturn;
+  return Val_unit;
+}
diff --git a/src/sdl_event_trans.c b/src/sdl_event_trans.c
new file mode 100644
index 0000000..09975e3
--- /dev/null
+++ b/src/sdl_event_trans.c
@@ -0,0 +1,24 @@
+#include <caml/mlvalues.h>
+#include <SDL.h>
+
+#include "sdl_event_trans.h"
+
+lookup_info ml_event_tag_table[] = {
+  {0, 16},
+  {Val_int(MLTAG_ACTIVE)      , SDL_ACTIVEEVENT},
+  {Val_int(MLTAG_KEYDOWN)     , SDL_KEYDOWN},
+  {Val_int(MLTAG_KEYUP)       , SDL_KEYUP},
+  {Val_int(MLTAG_MOTION)      , SDL_MOUSEMOTION},
+  {Val_int(MLTAG_BUTTONDOWN)  , SDL_MOUSEBUTTONDOWN},
+  {Val_int(MLTAG_BUTTONUP)    , SDL_MOUSEBUTTONUP},
+  {Val_int(MLTAG_JAXIS)       , SDL_JOYAXISMOTION},
+  {Val_int(MLTAG_JBALL)       , SDL_JOYBALLMOTION},
+  {Val_int(MLTAG_JHAT)        , SDL_JOYHATMOTION},
+  {Val_int(MLTAG_JBUTTONDOWN) , SDL_JOYBUTTONDOWN},
+  {Val_int(MLTAG_JBUTTONUP)   , SDL_JOYBUTTONUP},
+  {Val_int(MLTAG_RESIZE)      , SDL_VIDEORESIZE},
+  {Val_int(MLTAG_EXPOSE)      , SDL_VIDEOEXPOSE},
+  {Val_int(MLTAG_QUIT)        , SDL_QUIT},
+  {Val_int(MLTAG_USER)        , SDL_USEREVENT},
+  {Val_int(MLTAG_SYSWM)       , SDL_SYSWMEVENT}
+};
diff --git a/src/sdl_event_trans.h b/src/sdl_event_trans.h
new file mode 100644
index 0000000..30d0b8e
--- /dev/null
+++ b/src/sdl_event_trans.h
@@ -0,0 +1,25 @@
+#ifndef __SDL_EVENT_TAGS_H__
+#define __SDL_EVENT_TAGS_H__
+
+#include "common.h"
+
+#define MLTAG_ACTIVE      ( 0)
+#define MLTAG_KEYDOWN     ( 1)
+#define MLTAG_KEYUP       ( 2)
+#define MLTAG_MOTION      ( 3)
+#define MLTAG_BUTTONDOWN  ( 4)
+#define MLTAG_BUTTONUP    ( 5)
+#define MLTAG_JAXIS       ( 6)
+#define MLTAG_JBALL       ( 7)
+#define MLTAG_JHAT        ( 8)
+#define MLTAG_JBUTTONDOWN ( 9)
+#define MLTAG_JBUTTONUP   (10)
+#define MLTAG_RESIZE      (11)
+#define MLTAG_EXPOSE      (12)
+#define MLTAG_QUIT        (13)
+#define MLTAG_USER        (14)
+#define MLTAG_SYSWM       (15)
+
+extern lookup_info ml_event_tag_table[];
+
+#endif /* __SDL_EVENT_TAGS_H__ */
diff --git a/src/sdl_generic.c b/src/sdl_generic.c
index 9ae9644..abd3f06 100644
--- a/src/sdl_generic.c
+++ b/src/sdl_generic.c
@@ -1,9 +1,10 @@
-#include "common.h"
+#include <caml/mlvalues.h>

+#include "common.h"
 #include "sdl_generic.h"

-lookup_info ml_generic_button_table = {
-  {0, 2}
-  {Val_int(MLTAG_PRESSED), 1}
+lookup_info ml_generic_button_table[] = {
+  {0, 2},
+  {Val_int(MLTAG_PRESSED), 1},
   {Val_int(MLTAG_RELEASED), 0}
 };
diff --git a/src/sdl_initflags.h b/src/sdl_initflags.h
index 7fd8582..788c79a 100644
--- a/src/sdl_initflags.h
+++ b/src/sdl_initflags.h
@@ -1,8 +1,8 @@
-#ifndef __SDL_INITFLAGS_H__
-#define __SDL_INITFLAGS_H__
-
-#include "common.h"
-
+#ifndef __SDL_INITFLAGS_H__
+#define __SDL_INITFLAGS_H__
+
+#include "common.h"
+
 #define MLTAG_TIMER (474476363)
 #define MLTAG_VIDEO (-371943241)
 #define MLTAG_AUDIO (-891461267)
@@ -10,8 +10,8 @@
 #define MLTAG_JOYSTICK (-353443463)
 #define MLTAG_EVENTTHREAD (123518089)
 #define MLTAG_NOPARACHUTE (1032187521)
-#define MLTAG_EVERYTHING (566131943)
-
-extern lookup_info ml_init_flag_table[];
-
-#endif /*__SDL_INITFLAGS_H__*/
+#define MLTAG_EVERYTHING (566131943)
+
+extern lookup_info ml_init_flag_table[];
+
+#endif /*__SDL_INITFLAGS_H__*/
diff --git a/src/sdl_input.ml b/src/sdl_input.ml
index a15f5f7..74d0fe9 100644
--- a/src/sdl_input.ml
+++ b/src/sdl_input.ml
@@ -75,8 +75,9 @@ external get_mod_state: unit -> Sdl_key.modify_key list = "sdlcaml_get_mod_state
  *
  * @param delay how long key must be pressed
  * @param interval repeat speed
+ * @return true if succeeded.
  *)
-external enable_key_repeat: delay:int -> interval:int -> unit =
+external enable_key_repeat: delay:int -> interval:int -> bool =
   "sdlcaml_enable_key_repeat"

 (**
diff --git a/src/sdl_input_stub.c b/src/sdl_input_stub.c
index 81905a5..a4aa33f 100644
--- a/src/sdl_input_stub.c
+++ b/src/sdl_input_stub.c
@@ -4,9 +4,9 @@
 #include <caml/alloc.h>
 #include <caml/callback.h>

-
 #include "common.h"
-#include "sdl_input_trans.h"
+#include "sdl_generic.h"
+#include "sdl_key_trans.h"

 CAMLprim value sdlcaml_get_key_state(value unit) {
   CAMLparam0();
@@ -24,7 +24,7 @@ CAMLprim value sdlcaml_get_key_state(value unit) {
     int current_key = ml_lookup_to_c(ml_symkey_trans_table, Val_int(i));
     Store_field(tuple, 0, Val_int(i));
     Store_field(tuple, 1, ml_lookup_from_c(
-        ml_generic_button_state_table, keystates[current_key]));
+        ml_generic_button_table, keystates[current_key]));

     Store_field(preconvert_array, i, tuple);
   }
@@ -38,5 +38,63 @@ CAMLprim value sdlcaml_get_key_state(value unit) {
 }

 CAMLprim value get_mod_state(value unit) {
+  CAMLparam0();
+  CAMLlocal1(mod_list);
+  mod_list = Val_emptylist;
+
+  int mod_current_state = SDL_GetModState();
+
+  int key_trans_size = ml_table_size(ml_modkey_trans_table);
+  for (int i = 0; i < key_trans_size; ++i) {
+
+    /* contains pressing modify key only */
+    int current_key = ml_lookup_to_c(ml_modkey_trans_table, Val_int(i));
+    if (mod_current_state & current_key) {
+      mod_list = add_head(
+          mod_list,
+          ml_lookup_from_c(ml_modkey_trans_table, current_key));
+    }
+  }
+
+  CAMLreturn(mod_list);
+}
+
+CAMLprim value sdlcaml_enable_key_repeat(value delay, value interval) {
+  CAMLparam2(delay, interval);
+
+  int ret = SDL_EnableKeyRepeat(Int_val(delay), Int_val(interval));
+
+  if (ret == 0) {
+    CAMLreturn(Val_true);
+  } else {
+    CAMLreturn(Val_false);
+  }
+}
+
+CAMLprim value sdlcaml_get_mouse_state(value unit) {
+  CAMLparam0();
+  CAMLlocal2(button_state, mouse_state);
+
+  int x = 0, y = 0;
+  int current_buttons_state = SDL_GetMouseState(&x, &y);
+
+  const int MAX_BUTTON = 32;
+
+  /* get mouse state of as many as possible buttons */
+  for (int i = MAX_BUTTON; i > 0; --i) {
+    CAMLlocal1(state);
+    state = caml_alloc(2, 0);
+    Store_field(state, 0, Val_int(i));
+    Store_field(state, 1, ml_lookup_from_c(ml_generic_button_table,
+                                           current_buttons_state & SDL_BUTTON(i)));
+
+    button_state = add_head(button_state, state);
+  }
+
+  mouse_state = caml_alloc(3, 0);
+  Store_field(mouse_state, 0, Val_int(x));
+  Store_field(mouse_state, 1, Val_int(y));
+  Store_field(mouse_state, 2, button_state);

+  CAMLreturn(mouse_state);
 }
diff --git a/src/sdl_input_trans.c b/src/sdl_input_trans.c
index f39790d..8ed9d5e 100644
--- a/src/sdl_input_trans.c
+++ b/src/sdl_input_trans.c
@@ -5,14 +5,14 @@
 #include "sdl_input_trans.h"

 lookup_info ml_joyhat_trans_table[] = {
-{0, 9},
-{Val_int(MLTAG_HAT_CENTERED)  , SDL_HAT_CENTERED},
-{Val_int(MLTAG_HAT_UP)        , SDL_HAT_UP},
-{Val_int(MLTAG_HAT_RIGHT)     , SDL_HAT_RIGHT},
-{Val_int(MLTAG_HAT_DOWN)      , SDL_HAT_DOWN},
-{Val_int(MLTAG_HAT_LEFT)      , SDL_HAT_LEFT},
-{Val_int(MLTAG_HAT_RIGHTUP)   , SDL_HAT_RIGHTUP},
-{Val_int(MLTAG_HAT_RIGHTDOWN) , SDL_HAT_RIGHTDOWN},
-{Val_int(MLTAG_HAT_LEFTUP)    , SDL_HAT_LEFTUP},
-{Val_int(MLTAG_HAT_LEFTDOWN)  , SDL_HAT_LEFTDOWN}
+  {0, 9},
+  {Val_int(MLTAG_HAT_CENTERED)  , SDL_HAT_CENTERED},
+  {Val_int(MLTAG_HAT_UP)        , SDL_HAT_UP},
+  {Val_int(MLTAG_HAT_RIGHT)     , SDL_HAT_RIGHT},
+  {Val_int(MLTAG_HAT_DOWN)      , SDL_HAT_DOWN},
+  {Val_int(MLTAG_HAT_LEFT)      , SDL_HAT_LEFT},
+  {Val_int(MLTAG_HAT_RIGHTUP)   , SDL_HAT_RIGHTUP},
+  {Val_int(MLTAG_HAT_RIGHTDOWN) , SDL_HAT_RIGHTDOWN},
+  {Val_int(MLTAG_HAT_LEFTUP)    , SDL_HAT_LEFTUP},
+  {Val_int(MLTAG_HAT_LEFTDOWN)  , SDL_HAT_LEFTDOWN}
 };
diff --git a/src/sdl_key.ml b/src/sdl_key.ml
index 179b609..679a95d 100644
--- a/src/sdl_key.ml
+++ b/src/sdl_key.ml
@@ -1,4 +1,10 @@
+(**
+   this module contains key synonyms binding SDLK_* and Modify key
+   binding MODK_*.
+   In addition them, provide it that state map associate key with state what key is
+   pressed or released.

+*)

 (**
  * Mapping {b SDLkey}. These often uses with {!Sdl_KeyStateMap.state_map}
@@ -185,8 +191,8 @@ type state_map = Sdl_generic.button_state StateMap.t
    To reveive array is converted into {!state_map}.
 *)
 let to_state_map statearray =
-  let make_map map (key, state) = Map.add key state in
-  Array.fold_left make_map Map.empty statearray
+  let make_map (key, state) map = StateMap.add key state map in
+  Array.fold_right make_map statearray StateMap.empty

 let () =
   Callback.register "sdlcaml_ml_convert_state_map" to_state_map
diff --git a/src/sdl_key_trans.c b/src/sdl_key_trans.c
index 20869c7..eabd4dd 100644
--- a/src/sdl_key_trans.c
+++ b/src/sdl_key_trans.c
@@ -140,7 +140,7 @@ lookup_info ml_symkey_trans_table[] = {
 {Val_int(MLTAG_SDLK_EURO), SDLK_EURO}
 };

-lookup_info ml_modkey_trans_table = {
+lookup_info ml_modkey_trans_table[] = {
   {0, 12},
   {Val_int(MLTAG_KMOD_NONE), KMOD_NONE},
   {Val_int(MLTAG_KMOD_NUM), KMOD_NUM},
[from now] 2012/09/27 07:40:34

diff --git a/src/sdl_event_convert.c b/src/sdl_event_convert.c
index 05d6473..a717152 100644
--- a/src/sdl_event_convert.c
+++ b/src/sdl_event_convert.c
@@ -248,6 +248,7 @@ generic_lookup_info conversion_c2m_funcs[] = {

 /* create and return Event Structure for OCaml */
 value caml_convert_event_c2m(SDL_Event *event) {
+  CAMLparam0();
   if (event == NULL) {
     caml_invalid_argument("invalid event received : caml_convert_event_c2m");
   }
@@ -259,7 +260,7 @@ value caml_convert_event_c2m(SDL_Event *event) {
   value type = ml_lookup_from_c(ml_event_tag_table, event->type);
   convert_c2m func = (convert_c2m)ml_generic_lookup(conversion_c2m_funcs,
                                                     Int_val(type));
-  CAMLreturn((*func)(event, type))
+  CAMLreturn((*func)(event, type));
 }

 /*******************************************************************/
@@ -325,21 +326,21 @@ SDL_Event* caml_convert_m2c_keydown_event(value ml_event) {

 SDL_Event* caml_convert_m2c_mousemotion_event(value ml_event) {
   CAMLparam1(ml_event);
-  SDL_Event* e = malloc(0, sizeof(SDL_Event));
+  SDL_Event* e = malloc(sizeof(SDL_Event));
   e->type = SDL_MOUSEMOTION;

   const int MAX_BUTTON = 32;

-  event->motion.x = Int_val(Field(ml_event, 0));
-  event->motion.y = Int_val(Field(ml_event, 1));
-  event->motion.xrel = Int_val(Field(ml_event, 2));
-  event->motion.yrel = Int_val(Field(ml_event, 3));
+  e->motion.x = Int_val(Field(ml_event, 0));
+  e->motion.y = Int_val(Field(ml_event, 1));
+  e->motion.xrel = Int_val(Field(ml_event, 2));
+  e->motion.yrel = Int_val(Field(ml_event, 3));

   value button_state = Field(ml_event, 4);
   while (is_not_nil(button_state)) {
     CAMLlocal1(hd);
     hd = head(button_state);
-    int num = Int_val(hd, 0);
+    int num = Int_val(hd);
     int state = ml_lookup_to_c(ml_generic_button_table, Field(hd, 1));

     if (num >= MAX_BUTTON || num < 1) {
@@ -373,7 +374,7 @@ SDL_Event* caml_convert_m2c_mousebuttonup_event(value ml_event) {
   while (is_not_nil(button_state)) {
     CAMLlocal1(hd);
     hd = head(button_state);
-    int num = Int_val(hd, 0);
+    int num = Int_val(hd);
     int state = ml_lookup_to_c(ml_generic_button_table, Field(hd, 1));

     if (num >= MAX_BUTTON || num < 1) {
@@ -405,7 +406,7 @@ SDL_Event* caml_convert_m2c_mousebuttondown_event(value ml_event) {
   while (is_not_nil(button_state)) {
     CAMLlocal1(hd);
     hd = head(button_state);
-    int num = Int_val(hd, 0);
+    int num = Int_val(hd);
     int state = ml_lookup_to_c(ml_generic_button_table, Field(hd, 1));

     if (num >= MAX_BUTTON || num < 1) {
@@ -425,9 +426,9 @@ SDL_Event* caml_convert_m2c_joyaxismotion_event(value ml_event) {
   SDL_Event* e = malloc(sizeof(SDL_Event));
   e->type = SDL_JOYAXISMOTION;

-  event->jaxis.which = Int_val(Field(ml_event, 0));
-  event->jaxis.axis  = Int_val(Field(ml_event, 1));
-  event->jaxis.value = Int_val(Field(ml_event, 2));
+  e->jaxis.which = Int_val(Field(ml_event, 0));
+  e->jaxis.axis  = Int_val(Field(ml_event, 1));
+  e->jaxis.value = Int_val(Field(ml_event, 2));

   CAMLnoreturn;
   return e;
@@ -449,9 +450,8 @@ SDL_Event* caml_convert_m2c_joyballmotion_event(value ml_event) {

 SDL_Event* caml_convert_m2c_joyhatmotion_event(value ml_event) {
   CAMLparam1(ml_event);
-  int state  = event->jhat.value;
   SDL_Event* e = malloc(sizeof(SDL_Event));
-  e->type = SDL_JHATBUTTON;
+  e->type = SDL_JOYHATMOTION;;
   e->jhat.which = Int_val(Field(ml_event, 0));
   e->jhat.hat = Int_val(Field(ml_event, 1));

@@ -460,8 +460,8 @@ SDL_Event* caml_convert_m2c_joyhatmotion_event(value ml_event) {
   /* restore hat switch value from OCaml value */
   value hatbutton = Field(ml_event, 2);
   while (is_not_nil(hatbutton)) {
-    hatbutton_value &= ml_lookup_to_c(head(hatbutton));
-    hatbutton = tail(list);
+    hatbutton_value &= ml_lookup_to_c(ml_event_tag_table, head(hatbutton));
+    hatbutton = tail(hatbutton);
   }

   e->jhat.value = hatbutton_value;
@@ -553,11 +553,11 @@ SDL_Event* caml_convert_event_m2c(value ml_event) {
       case MLTAG_KEYDOWN: event     = caml_convert_m2c_keydown_event(e_struct); break;
       case MLTAG_KEYUP: event       = caml_convert_m2c_keyup_event(e_struct); break;
       case MLTAG_MOTION: event      = caml_convert_m2c_mousemotion_event(e_struct); break;
-      case MLTAG_BUTTONDOWN: event  = caml_convert_m2c_buttondown_event(e_struct); break;
-      case MLTAG_BUTTONUP: event    = caml_convert_m2c_buttonup_event(e_struct); break;
-      case MLTAG_JAXIS: event       = caml_convert_m2c_jaxis_event(e_struct); break;
-      case MLTAG_JBALL: event       = caml_convert_m2c_jball_event(e_struct); break;
-      case MLTAG_JHAT: event        = caml_convert_m2c_jhat_event(e_struct); break;
+      case MLTAG_BUTTONDOWN: event  = caml_convert_m2c_mousebuttondown_event(e_struct); break;
+      case MLTAG_BUTTONUP: event    = caml_convert_m2c_mousebuttonup_event(e_struct); break;
+      case MLTAG_JAXIS: event       = caml_convert_m2c_joyaxismotion_event(e_struct); break;
+      case MLTAG_JBALL: event       = caml_convert_m2c_joyballmotion_event(e_struct); break;
+      case MLTAG_JHAT: event        = caml_convert_m2c_joyhatmotion_event(e_struct); break;
       case MLTAG_JBUTTONDOWN: event = caml_convert_m2c_jbuttondown_event(e_struct); break;
       case MLTAG_JBUTTONUP: event   = caml_convert_m2c_jbuttonup_event(e_struct); break;
       case MLTAG_RESIZE: event      = caml_convert_m2c_resize_event(e_struct); break;
diff --git a/src/sdl_generic.h b/src/sdl_generic.h
index 4108fcd..01cce05 100644
--- a/src/sdl_generic.h
+++ b/src/sdl_generic.h
@@ -1,11 +1,11 @@
-#ifndef __SDL_GENERIC_H__
-#define __SDL_GENERIC_H__
-
-#include "common.h"
-
+#ifndef __SDL_GENERIC_H__
+#define __SDL_GENERIC_H__
+
+#include "common.h"
+
 #define MLTAG_PRESSED (-210416379)
-#define MLTAG_RELEASED (551170427)
-
-extern lookup_info ml_generic_button_table[];
-
-#endif /*__SDL_GENERIC_H__*/
+#define MLTAG_RELEASED (551170427)
+
+extern lookup_info ml_generic_button_table[];
+
+#endif /*__SDL_GENERIC_H__*/
diff --git a/src/sdl_initflags.h b/src/sdl_initflags.h
index 788c79a..7fd8582 100644
--- a/src/sdl_initflags.h
+++ b/src/sdl_initflags.h
@@ -1,8 +1,8 @@
-#ifndef __SDL_INITFLAGS_H__
-#define __SDL_INITFLAGS_H__
-
-#include "common.h"
-
+#ifndef __SDL_INITFLAGS_H__
+#define __SDL_INITFLAGS_H__
+
+#include "common.h"
+
 #define MLTAG_TIMER (474476363)
 #define MLTAG_VIDEO (-371943241)
 #define MLTAG_AUDIO (-891461267)
@@ -10,8 +10,8 @@
 #define MLTAG_JOYSTICK (-353443463)
 #define MLTAG_EVENTTHREAD (123518089)
 #define MLTAG_NOPARACHUTE (1032187521)
-#define MLTAG_EVERYTHING (566131943)
-
-extern lookup_info ml_init_flag_table[];
-
-#endif /*__SDL_INITFLAGS_H__*/
+#define MLTAG_EVERYTHING (566131943)
+
+extern lookup_info ml_init_flag_table[];
+
+#endif /*__SDL_INITFLAGS_H__*/