(shift_state): Fix the condition of taking init actions.
[m17n/m17n-lib.git] / src / input.c
index 0405540..3c3d55e 100644 (file)
@@ -1,5 +1,5 @@
 /* input.c -- input method module.
-   Copyright (C) 2003, 2004
+   Copyright (C) 2003, 2004, 2005
      National Institute of Advanced Industrial Science and Technology (AIST)
      Registration Number H15PRO112
 
     @addtogroup m17nInputMethod
     @brief ÆþÎϥ᥽¥Ã¥ÉÍÑAPI.
 
-    ÆþÎϥ᥽¥Ã¥É¤Ï¿ÍͤÊʸ»ú¤òÆþÎϤ¹¤ë¤¿¤á¤Î¥ª¥Ö¥¸¥§¥¯¥È¤Ç¤¢¤ë¡£ÆþÎÏ¥á
-    ¥½¥Ã¥É¤Ï¥·¥ó¥Ü¥ë LANGUAGE ¤È NAME ¤ÎÁȤˤè¤Ã¤Æ¼±Ê̤µ¤ì¡¢¤³¤ÎÁȤˤè¤Ã
-    ¤ÆÆþÎϥ᥽¥Ã¥É¥É¥é¥¤¥Ð¤¬·è¤Þ¤ë¡£ÆþÎϥ᥽¥Ã¥É¥É¥é¥¤¥Ð¤È¤Ï¤¢¤ëÆþÎÏ¥á
-    ¥½¥Ã¥É¤ò°·¤¦¤¿¤á¤Î´Ø¿ô¤Î½¸¤Þ¤ê¤Ç¤¢¤ë¡£ ÆþÎϥ᥽¥Ã¥É¤Ë¤ÏÆâÉô¥á¥½¥Ã
-    ¥É¤È³°Éô¥á¥½¥Ã¥É¤ÎÆóÄ̤꤬¤¢¤ë¡£
+    ÆþÎϥ᥽¥Ã¥É¤Ï¿ÍͤÊʸ»ú¤òÆþÎϤ¹¤ë¤¿¤á¤Î¥ª¥Ö¥¸¥§¥¯¥È¤Ç¤¢¤ë¡£
+    ÆþÎϥ᥽¥Ã¥É¤Ï¥·¥ó¥Ü¥ë LANGUAGE ¤È NAME ¤ÎÁȤˤè¤Ã¤Æ¼±Ê̤µ¤ì¡¢
+    ¤³¤ÎÁȹ礻¤Ë¤è¤Ã¤ÆÆþÎϥ᥽¥Ã¥É¥É¥é¥¤¥Ð¤¬·èÄꤹ¤ë¡£
+    ÆþÎϥ᥽¥Ã¥É¥É¥é¥¤¥Ð¤È¤Ï¡¢¤¢¤ëÆþÎϥ᥽¥Ã¥É¤ò°·¤¦¤¿¤á¤Î´Ø¿ô¤Î½¸¤Þ¤ê¤Ç¤¢¤ë¡£
+    ÆþÎϥ᥽¥Ã¥É¤Ë¤ÏÆâÉô¥á¥½¥Ã¥É¤È³°Éô¥á¥½¥Ã¥É¤ÎÆó¼ïÎब¤¢¤ë¡£
 
     <ul> 
     <li> ÆâÉôÆþÎϥ᥽¥Ã¥É
 
-    ÆâÉôÆþÎϥ᥽¥Ã¥É¤Ï LANGUAGE ¤¬ @c Mnil °Ê³°¤Î¤â¤Î¤Ç¤¢¤ê¡¢ËÜÂΤÏ
-    m17n ¥Ç¡¼¥¿¥Ù¡¼¥¹¤Ë <Minput_method, LANGUAGE, NAME>¤È¤¤¤¦¥¿¥°ÉÕ¤­
-    ¤ÇÄêµÁ¤µ¤ì¤Æ¤¤¤ë¡£¤³¤Î¼ï¤ÎÆþÎϥ᥽¥Ã¥É¤ËÂФ·¤Æ¡¢m17n ¥é¥¤¥Ö¥é¥ê¤Ë
-    ¤ÏCUIÍѤÈGUIÍѤ½¤ì¤¾¤ì¤ÎÆþÎϥ᥽¥Ã¥É¥É¥é¥¤¥Ð¤¬¤¢¤é¤«¤¸¤á½àÈ÷¤µ¤ì¤Æ
-    ¤¤¤ë¡£¤³¤ì¤é¤Î¥É¥é¥¤¥Ð¤Ïm17n¥é¥¤¥Ö¥é¥ê¼«¿È¤ÎÆþÎϽèÍý¥¨¥ó¥¸¥ó¤òÍøÍÑ
-    ¤¹¤ë¡£m17n ¥Ç¡¼¥¿¥Ù¡¼¥¹¤Ë¤Ï¡¢ÆÃÄê¤Î¸À¸ìÀìÍѤǤʤ¤ÆþÎϥ᥽¥Ã¥É¤âÄê
-    µÁ¤¹¤ë¤³¤È¤¬¤Ç¤­¡¢¤½¤Î¤è¤¦¤ÊÆþÎϥ᥽¥Ã¥É¤Î LANGUAGE ¤Ï @c Mt ¤Ç¤¢
-    ¤ë¡£
-
-    ÆâÉôÆþÎϥ᥽¥Ã¥É¤Ï¡¢¥æ¡¼¥¶¤ÎÆþÎÏ¥¤¥Ù¥ó¥È¤ËÂбþ¤·¤¿¥·¥ó¥Ü¥ë¤Ç¤¢¤ëÆþ
-    ÎÏ¥­¡¼¤ò¼õ¤±¼è¤ë¡£@c m17n @c ¥é¥¤¥Ö¥é¥ê ¤ÏÆþÎÏ¥¤¥Ù¥ó¥È¤¬¥¢¥×¥ê¥±¡¼
-    ¥·¥ç¥ó¥×¥í¥°¥é¥à¤Ç¤É¤¦É½¸½¤µ¤ì¤Æ¤¤¤ë¤«¤òÃΤë½Ñ¤ò»ý¤¿¤Ê¤¤¤Î¤Ç¡¢ÆþÎÏ
-    ¥¤¥Ù¥ó¥È¤«¤éÆþÎÏ¥­¡¼¤Ø¤ÎÊÑ´¹¤Ï¥¢¥×¥ê¥±¡¼¥·¥ç¥ó¥×¥í¥°¥é¥Þ¤ÎÀÕǤ¤Ç¹Ô
-    ¤ï¤Ê¤¯¤Æ¤Ï¤Ê¤é¤Ê¤¤¡£¾ÜºÙ¤Ë¤Ä¤¤¤Æ¤Ï´Ø¿ô minput_event_to_key () ¤ÎÀâ
-    ÌÀ¤ò»²¾È¡£
+    ÆâÉôÆþÎϥ᥽¥Ã¥É¤È¤Ï LANGUAGE ¤¬ @c Mnil °Ê³°¤Î¤â¤Î¤Ç¤¢¤ê¡¢¤½¤ÎËÜÂΤÏm17n ¥Ç¡¼¥¿¥Ù¡¼¥¹¤Ë
+    <Minput_method, LANGUAGE, NAME> 
+    ¤È¤¤¤¦¥¿¥°¤òÉÕ¤±¤ÆÄêµÁ¤µ¤ì¤Æ¤¤¤ë¡£
+    ¤³¤Î¼ï¤ÎÆþÎϥ᥽¥Ã¥É¤ËÂФ·¤Æ¡¢m17n ¥é¥¤¥Ö¥é¥ê¤Ç¤Ï
+    CUI ÍѤȠGUI ÍѤ½¤ì¤¾¤ì¤ÎÆþÎϥ᥽¥Ã¥É¥É¥é¥¤¥Ð¤ò¤¢¤é¤«¤¸¤áÄêµÁ¤·¤Æ¤¤¤ë¡£
+    ¤³¤ì¤é¤Î¥É¥é¥¤¥Ð¤Ï m17n ¥é¥¤¥Ö¥é¥ê¼«ÂΤÎÆþÎϽèÍý¥¨¥ó¥¸¥ó¤òÍøÍѤ¹¤ë¡£
+    m17n ¥Ç¡¼¥¿¥Ù¡¼¥¹¤Ë¤Ï¡¢ÆÃÄê¤Î¸À¸ìÀìÍѤǤʤ¤ÆþÎϥ᥽¥Ã¥É¤òÄêµÁ¤¹¤ë¤³¤È¤â¤Ç¤­¡¢
+    ¤½¤Î¤è¤¦¤ÊÆþÎϥ᥽¥Ã¥É¤Î LANGUAGE ¤Ï @c Mt ¤Ç¤¢¤ë¡£
+
+    ÆâÉôÆþÎϥ᥽¥Ã¥É¤Ï¡¢¥æ¡¼¥¶¤ÎÆþÎÏ¥¤¥Ù¥ó¥È¤ËÂбþ¤·¤¿¥·¥ó¥Ü¥ë¤Ç¤¢¤ëÆþÎÏ¥­¡¼¤ò¼õ¤±¼è¤ë¡£
+    @c m17n @c ¥é¥¤¥Ö¥é¥ê ¤ÏÆþÎÏ¥¤¥Ù¥ó¥È¤¬¥¢¥×¥ê¥±¡¼¥·¥ç¥ó¥×¥í¥°¥é¥à¤Ç¤É¤¦É½¸½¤µ¤ì¤Æ¤¤¤ë¤«¤òÃΤ뤳¤È¤¬¤Ç¤­¤Ê¤¤¤Î¤Ç¡¢
+    ÆþÎÏ¥¤¥Ù¥ó¥È¤«¤éÆþÎÏ¥­¡¼¤Ø¤ÎÊÑ´¹¤Ï¥¢¥×¥ê¥±¡¼¥·¥ç¥ó¥×¥í¥°¥é¥Þ¤ÎÀÕǤ¤Ç¹Ô¤ï¤Ê¤¯¤Æ¤Ï¤Ê¤é¤Ê¤¤¡£
+    ¾ÜºÙ¤Ë¤Ä¤¤¤Æ¤Ï´Ø¿ô minput_event_to_key () ¤ÎÀâÌÀ¤ò»²¾È¡£
 
     <li> ³°ÉôÆþÎϥ᥽¥Ã¥É
 
-    ³°ÉôÆþÎϥ᥽¥Ã¥É¤Ï LANGUAGE ¤¬ @c Mnil ¤Î¤â¤Î¤Ç¤¢¤ê¡¢ËÜÂΤϳ°Éô¤Î
-    ¥ê¥½¡¼¥¹¤È¤·¤ÆÄêµÁ¤µ¤ì¤ë¡£¡Ê¤¿¤È¤¨¤ÐX Window System ¤ÎXIM ¤Ê¤É¡£) 
-    ¤³¤Î¼ï¤ÎÆþÎϥ᥽¥Ã¥É¤Ç¤Ï¡¢¥·¥ó¥Ü¥ë NAME ¤Ï@c Minput_driver ¤ò¥­¡¼
-    ¤È¤¹¤ë¥×¥í¥Ñ¥Æ¥£¤ò»ý¤Á¡¢¤½¤ÎÃͤÏÆþÎϥ᥽¥Ã¥É¥É¥é¥¤¥Ð¤Ø¤Î¥Ý¥¤¥ó¥¿¤Ç
-    ¤Ê¤¯¤Æ¤Ï¤Ê¤é¤Ê¤¤¡£¤·¤¿¤¬¤Ã¤Æ¡¢Å¬Àڤʥɥ饤¥Ð¤ò½àÈ÷¤¹¤ë¤³¤È¤Ë¤è¤Ã¤Æ¡¢
-    ¤¤¤«¤Ê¤ë¼ïÎà¤ÎÆþÎϥ᥽¥Ã¥É¤â @c m17n @c ¥é¥¤¥Ö¥é¥ê ¤ÎÏÈÁȤÎÃæ¤Ç°·
-    ¤¦»ö¤¬¤Ç¤­¤ë¡£
+    ³°ÉôÆþÎϥ᥽¥Ã¥É¤È¤Ï LANGUAGE ¤¬ @c Mnil ¤Î¤â¤Î¤Ç¤¢¤ê¡¢¤½¤ÎËÜÂΤϳ°Éô¤Î¥ê¥½¡¼¥¹¤È¤·¤ÆÄêµÁ¤µ¤ì¤ë¡£
+    ¡Ê¤¿¤È¤¨¤ÐX Window System ¤ÎXIM ¤Ê¤É¡£) 
+    ¤³¤Î¼ï¤ÎÆþÎϥ᥽¥Ã¥É¤Ç¤Ï¡¢¥·¥ó¥Ü¥ë NAME ¤Ï@c Minput_driver 
+    ¤ò¥­¡¼¤È¤¹¤ë¥×¥í¥Ñ¥Æ¥£¤ò»ý¤Á¡¢¤½¤ÎÃͤÏÆþÎϥ᥽¥Ã¥É¥É¥é¥¤¥Ð¤Ø¤Î¥Ý¥¤¥ó¥¿¤Ç¤¢¤ë¡£
+    ¤³¤Î¤³¤È¤Ë¤è¤ê¡¢Å¬Àڤʥɥ饤¥Ð¤ò½àÈ÷¤¹¤ë¤³¤È¤Ë¤è¤Ã¤Æ¡¢¤¤¤«¤Ê¤ë¼ïÎà¤ÎÆþÎϥ᥽¥Ã¥É¤â
+    @c m17n @c ¥é¥¤¥Ö¥é¥ê ¤ÎÏÈÁȤÎÃæ¤Ç°·¤¦»ö¤¬¤Ç¤­¤ë¡£
 
-    ÍøÊØÀ­¤Î¤¿¤á¡¢m17n X ¥é¥¤¥Ö¥é¥ê¤Ï XIM ¤Î OverTheSpot ¤ÎÆþÎÏ¥¹¥¿¥¤¥ë
-    ¤ò¼Â¸½¤¹¤ëÆþÎϥ᥽¥Ã¥É¥É¥é¥¤¥Ð¤òÄ󶡤·¡¢¤Þ¤¿¥·¥ó¥Ü¥ë @c Mxim ¤Î @c
-    Minput_driver ¥×¥í¥Ñ¥Æ¥£¤ÎÃͤȤ·¤Æ¤½¤Î¥É¥é¥¤¥Ð¤Ø¤Î¥Ý¥¤¥ó¥¿¤òÊÝ»ý¤·
-    ¤Æ¤¤¤ë¡£¾ÜºÙ¤Ë¤Ä¤¤¤Æ¤Ï m17n GUI API ¤Î¥É¥­¥å¥á¥ó¥È¤ò»²¾È¤Î¤³¤È¡£
+    ÍøÊØÀ­¤Î´ÑÅÀ¤«¤é¡¢m17n X ¥é¥¤¥Ö¥é¥ê¤Ï XIM ¤Î OverTheSpot 
+    ¤ÎÆþÎÏ¥¹¥¿¥¤¥ë¤ò¼Â¸½¤¹¤ëÆþÎϥ᥽¥Ã¥É¥É¥é¥¤¥Ð¤òÄ󶡤·¡¢¤Þ¤¿¥·¥ó¥Ü¥ë @c Mxim ¤Î 
+    @c Minput_driver ¥×¥í¥Ñ¥Æ¥£¤ÎÃͤȤ·¤Æ¤½¤Î¥É¥é¥¤¥Ð¤Ø¤Î¥Ý¥¤¥ó¥¿¤òÊÝ»ý¤·¤Æ¤¤¤ë¡£
+    ¾ÜºÙ¤Ë¤Ä¤¤¤Æ¤Ï m17n GUI API ¤Î¥É¥­¥å¥á¥ó¥È¤ò»²¾È¤Î¤³¤È¡£
 
     </ul> 
 
 
 #include <stdio.h>
 #include <string.h>
+#include <sys/types.h>
+#include <dirent.h>
 
 #include "config.h"
 
 #include "input.h"
 #include "symbol.h"
 #include "plist.h"
+#include "database.h"
 
 static int mdebug_mask = MDEBUG_INPUT;
 
@@ -177,6 +177,8 @@ static MSymbol one_char_symbol[256];
 
 static MSymbol M_key_alias;
 
+static MSymbol M_description, M_command, M_variable;
+
 /** Structure to hold a map.  */
 
 struct MIMMap
@@ -373,7 +375,22 @@ parse_action_list (MPlist *plist, MPlist *macros)
            }
          else if (action_name == Mpushback)
            {
-             if (! MPLIST_INTEGER_P (pl))
+             if (MPLIST_MTEXT_P (pl))
+               {
+                 MText *mt = MPLIST_MTEXT (pl);
+
+                 if (mtext_nchars (mt) != mtext_nbytes (mt))
+                   MERROR (MERROR_IM, -1);                 
+               }
+             else if (MPLIST_PLIST_P (pl))
+               {
+                 MPlist *p;
+
+                 MPLIST_DO (p, MPLIST_PLIST (pl))
+                   if (! MPLIST_SYMBOL_P (p))
+                     MERROR (MERROR_IM, -1);
+               }
+             else if (! MPLIST_INTEGER_P (pl))
                MERROR (MERROR_IM, -1);
            }
          else if (action_name == Mset || action_name == Madd
@@ -577,10 +594,6 @@ load_macros (MPlist *plist, MPlist *macros)
       PLIST ::= ( MODULE-NAME FUNCTION * )
    EXTERNALS is a plist of MODULE-NAME vs (MIMExternalModule *).  */
 
-#ifndef DLOPEN_SHLIB_EXT
-#define DLOPEN_SHLIB_EXT ".so"
-#endif
-
 static int
 load_external_module (MPlist *plist, MPlist *externals)
 {
@@ -822,7 +835,7 @@ shift_state (MInputContext *ic, MSymbol state_name)
   if (! state)
     state = (MIMState *) MPLIST_VAL (im_info->states);
 
-  MDEBUG_PRINT1 ("\n[IM] state-shift (%s)", MSYMBOL_NAME (state->name));
+  MDEBUG_PRINT1 ("\n  [IM] (shift %s)", MSYMBOL_NAME (state->name));
 
   /* Enter the new state.  */
   ic_info->state = state;
@@ -854,8 +867,6 @@ shift_state (MInputContext *ic, MSymbol state_name)
       ic->preedit_changed = ic->candidates_changed = 1;
       MPLIST_DO (p, ic_info->markers)
        MPLIST_VAL (p) = 0;
-      MPLIST_DO (p, ic_info->vars)
-       MPLIST_VAL (p) = 0;
       ic->cursor_pos = 0;
       memmove (ic_info->keys, ic_info->keys + ic_info->state_key_head,
               sizeof (int) * (ic_info->used - ic_info->state_key_head));
@@ -868,8 +879,7 @@ shift_state (MInputContext *ic, MSymbol state_name)
   if (! ic->status)
     ic->status = im_info->title;
   ic->status_changed = 1;
-  if (ic_info->key_head == ic_info->used
-      && ic_info->map == ic_info->state->map
+  if (ic_info->map == ic_info->state->map
       && ic_info->map->map_actions)
     {
       MDEBUG_PRINT (" init-actions:");
@@ -1218,14 +1228,51 @@ take_action_list (MInputContext *ic, MPlist *action_list)
        }
       else if (name == Mpushback)
        {
-         int num = MPLIST_INTEGER (args);
+         if (MPLIST_INTEGER_P (args))
+           {
+             int num = MPLIST_INTEGER (args);
+
+             if (num > 0)
+               ic_info->key_head -= num;
+             else
+               ic_info->key_head = num;
+             if (ic_info->key_head > ic_info->used)
+               ic_info->key_head = ic_info->used;
+           }
+         else if (MPLIST_MTEXT_P (args))
+           {
+             MText *mt = MPLIST_MTEXT (args);
+             int i, len = mtext_nchars (mt);
+             MSymbol key;
 
-         if (num > 0)
-           ic_info->key_head -= num;
+             ic_info->key_head--;
+             for (i = 0; i < len; i++)
+               {
+                 key = one_char_symbol[MTEXT_DATA (mt)[i]];
+                 if (ic_info->key_head + i < ic_info->used)
+                   ic_info->keys[ic_info->key_head + i] = key;
+                 else
+                   MLIST_APPEND1 (ic_info, keys, key, MERROR_IM);
+               }
+           }
          else
-           ic_info->key_head = num;
-         if (ic_info->key_head > ic_info->used)
-           ic_info->key_head = ic_info->used;
+           {
+             MPlist *plist = MPLIST_PLIST (args), *pl;
+             int i = 0;
+             MSymbol key;
+
+             ic_info->key_head--;
+
+             MPLIST_DO (pl, plist)
+               {
+                 key = MPLIST_SYMBOL (pl);
+                 if (ic_info->key_head < ic_info->used)
+                   ic_info->keys[ic_info->key_head + i] = key;
+                 else
+                   MLIST_APPEND1 (ic_info, keys, key, MERROR_IM);
+                 i++;
+               }
+           }
        }
       else if (name == Mcall)
        {
@@ -1337,12 +1384,20 @@ take_action_list (MInputContext *ic, MPlist *action_list)
            actions2 = NULL;
          else
            actions2 = MPLIST_PLIST (args);
+         MDEBUG_PRINT2 ("(%d,%d)", val1, val2);
          if (name == Mequal ? val1 == val2
              : name == Mless ? val1 < val2
              : val1 > val2)
-           ret = take_action_list (ic, actions1);
-         else if (actions2)
-           ret = take_action_list (ic, actions2);
+           {
+             MDEBUG_PRINT ("ok");
+             ret = take_action_list (ic, actions1);
+           }
+         else
+           {
+             MDEBUG_PRINT ("no");
+             if (actions2)
+               ret = take_action_list (ic, actions2);
+           }
          if (ret < 0)
            return ret;
        }
@@ -1395,14 +1450,16 @@ handle_key (MInputContext *ic)
   MSymbol key = ic_info->keys[ic_info->key_head];
   int i;
 
-  MDEBUG_PRINT2 ("[IM] handle `%s' in state %s", 
+  MDEBUG_PRINT2 ("  [IM] handle `%s' in state %s", 
                 MSYMBOL_NAME (key), MSYMBOL_NAME (ic_info->state->name));
 
   if (map->submaps)
     {
+      MSymbol alias;
+
       submap = mplist_get (map->submaps, key);
-      if (! submap && (key = msymbol_get (key, M_key_alias)) != Mnil)
-       submap = mplist_get (map->submaps, key);
+      if (! submap && (alias = msymbol_get (key, M_key_alias)) != Mnil)
+       submap = mplist_get (map->submaps, alias);
     }
 
   if (submap)
@@ -1416,7 +1473,10 @@ handle_key (MInputContext *ic)
        {
          MDEBUG_PRINT (" map-actions:");
          if (take_action_list (ic, map->map_actions) < 0)
-           return -1;
+           {
+             MDEBUG_PRINT ("\n");
+             return -1;
+           }
        }
       else if (map->submaps)
        {
@@ -1439,14 +1499,16 @@ handle_key (MInputContext *ic)
            {
              MDEBUG_PRINT (" branch-actions:");
              if (take_action_list (ic, map->branch_actions) < 0)
-               return -1;
+               {
+                 MDEBUG_PRINT ("\n");
+                 return -1;
+               }
            }
          /* If MAP is still not the root map, shift to the current
             state.  */
          if (ic_info->map != ic_info->state->map)
            shift_state (ic, ic_info->state->name);
        }
-      MDEBUG_PRINT ("\n");
     }
   else
     {
@@ -1495,8 +1557,8 @@ handle_key (MInputContext *ic)
            shift_state (ic,
                         ((MIMState *) MPLIST_VAL (im_info->states))->name);
        }
-      MDEBUG_PRINT ("\n");
     }
+  MDEBUG_PRINT ("\n");
   return 0;
 }
 
@@ -1514,6 +1576,7 @@ reset_ic (MInputContext *ic, MSymbol ignore)
   MLIST_RESET (ic_info);
   ic_info->map = ic_info->state ? ic_info->state->map : NULL;
   ic_info->state_key_head = ic_info->key_head = 0;
+  ic_info->key_unhandled = 0;
   ic->cursor_pos = ic_info->state_pos = 0;
   ic->status = ic_info->state ? ic_info->state->title : NULL;
   if (! ic->status)
@@ -1521,8 +1584,6 @@ reset_ic (MInputContext *ic, MSymbol ignore)
   ic->candidate_list = NULL;
   ic->candidate_show = 0;
   ic->status_changed = ic->preedit_changed = ic->candidates_changed = 1;
-  if (ic_info->map && ic_info->map->map_actions)
-    take_action_list (ic, ic_info->map->map_actions);
 }
 
 static int
@@ -1741,6 +1802,350 @@ lookup (MInputContext *ic, MSymbol key, void *arg, MText *mt)
   return (((MInputContextInfo *) ic->info)->key_unhandled ? -1 : 0);
 }
 
+static MPlist *load_im_info_keys;
+
+static MPlist *
+load_im_info (MSymbol language, MSymbol name, MSymbol key)
+{
+  MDatabase *mdb;
+  MPlist *plist;
+
+  if (language == Mnil || name == Mnil)
+    MERROR (MERROR_IM, NULL);
+
+  mdb = mdatabase_find (Minput_method, language, name, Mnil);
+  if (! mdb)
+    MERROR (MERROR_IM, NULL);
+  mplist_push (load_im_info_keys, key, Mt);
+  plist = mdatabase__load_for_keys (mdb, load_im_info_keys);
+  mplist_pop (load_im_info_keys);
+  return plist;
+}
+
+\f
+/* Input method command handler.  */
+
+/* List of all (global and local) commands. 
+   (LANG:(IM-NAME:(COMMAND ...) ...) ...) ...
+   COMMAND is CMD-NAME:(mtext:DESCRIPTION plist:KEYSEQ ...))
+   Global commands are storead as (t (t COMMAND ...))  */
+static MPlist *command_list;
+
+/* Check if PLIST is a valid command key sequence.
+   PLIST must be NULL or:
+   [ symbol:KEY | integer:KEY ] ...  */
+
+static int
+check_command_keyseq (MPlist *plist)
+{
+  if (! plist)
+    return 0;
+  MPLIST_DO (plist, plist)
+    {
+      if (MPLIST_SYMBOL_P (plist))
+       continue;
+      else if (MPLIST_INTEGER_P (plist))
+       {
+         int n = MPLIST_INTEGER (plist);
+
+         if (n < 0 || n > 9)
+           return -1;
+         MPLIST_KEY (plist) = Msymbol;
+         MPLIST_VAL (plist) = one_char_symbol['0' + 9];
+       }
+      else
+       return -1;
+    }
+  return 0;
+}
+
+static MText *
+get_description_advance (MPlist *plist)
+{
+  MText *mt;
+  int pos;
+
+  if (! MPLIST_MTEXT_P (plist))
+    return NULL;
+  mt = mplist_pop (plist);
+  pos = mtext_chr (mt, '\n'); 
+  if (pos > 0)
+    {
+      MText *detail = mtext_copy (mtext (), 0, mt, pos + 1, mtext_nchars (mt));
+      mtext_del (mt, pos, mtext_nchars (mt));
+      mtext_put_prop (mt, 0, pos, Mdetail_text, detail);
+      M17N_OBJECT_UNREF (detail);
+    }
+  return mt;
+}
+
+static MPlist *
+parse_command_list (MPlist *plist, MPlist *global_list)
+{
+  MPlist *val = mplist ();
+
+  /* PLIST ::= (sym:CMD mtext:DESCRIPTION ? (sym:KEY ...) ...) ... */
+  MPLIST_DO (plist, plist)
+    {
+      MSymbol cmd;
+      MText *mt;
+      MPlist *this_val, *pl, *p;
+
+      if (! MPLIST_PLIST_P (plist))
+       continue;
+      pl = MPLIST_PLIST (plist);
+      if (! MPLIST_SYMBOL_P (pl))
+       continue;
+      cmd = MPLIST_SYMBOL (pl);
+      pl = MPLIST_NEXT (pl);
+      mt = get_description_advance (pl);
+      this_val = mplist ();
+
+      if (! mt && global_list)
+       {
+         /* Get the description from global_list.  */
+         p = mplist_get (global_list, cmd);
+         if (p && MPLIST_MTEXT (p))
+           {
+             mt = MPLIST_MTEXT (p);
+             M17N_OBJECT_REF (mt);
+           }
+       }
+      if (! mt)
+       mt = mtext ();
+      mplist_add (this_val, Mtext, mt);
+      M17N_OBJECT_UNREF (mt);
+
+      /* PL ::= (sym:KEY ...) ... */
+      MPLIST_DO (pl, pl)
+       {
+         if (MPLIST_PLIST_P (pl)
+             && check_command_keyseq (MPLIST_PLIST (pl)) >= 0)
+           /* All the elements are valid keys.  */
+           mplist_add (this_val, Mplist, MPLIST_PLIST (pl));
+       }
+
+      mplist_put (val, cmd, this_val);
+    }
+  return val;
+}
+
+static MPlist *
+get_command_list (MSymbol language, MSymbol name)
+{
+  MPlist *per_lang;
+  MPlist *plist, *pl;
+
+  if (name == Mnil)
+    language = name = Mt;
+
+  if (! command_list)
+    {
+      MDatabase *mdb = mdatabase_find (msymbol ("input"), M_command,
+                                      Mnil, Mnil);
+
+      if (mdb && (plist = mdatabase_load (mdb)))
+       {
+         pl = parse_command_list (plist, NULL);
+         M17N_OBJECT_UNREF (plist);
+       }
+      else
+       pl = mplist ();
+      plist = mplist ();
+      mplist_add (plist, Mt, pl);
+      command_list = mplist ();
+      mplist_add (command_list, Mt, plist);
+    }
+
+  per_lang = mplist_get (command_list, language);
+  if (per_lang)
+    {
+      plist = mplist_find_by_key (per_lang, name);
+      if (plist)
+       return (MPLIST_VAL (plist));
+    }
+  else
+    {
+      per_lang = mplist ();
+      mplist_add (command_list, language, per_lang);
+    }
+
+  /* Now we are sure that we are loading per-im info.  */
+  /* Get the global command list.  */
+  plist = load_im_info (language, name, M_command);
+  if (! plist || mplist_key (plist) == Mnil)
+    {
+      if (! plist)
+       plist = mplist ();
+      mplist_add (per_lang, name, plist);
+      return plist;
+    }
+  pl = parse_command_list (mplist_value (plist),
+                          mplist_get ((MPlist *) mplist_get (command_list, Mt),
+                                      Mt));
+  M17N_OBJECT_UNREF (plist);
+  mplist_put (per_lang, name, pl);
+  return pl;
+}
+
+\f
+/* Input method variable handler.  */
+
+/* List of all variables. 
+   (LANG:(IM-NAME:(VAR ...) ...) ...) ...
+   VAR is VAR-NAME:(mtext:DESCRIPTION TYPE:VALUE ...))  */
+
+static MPlist *variable_list;
+
+static MPlist *
+parse_variable_list (MPlist *plist)
+{
+  MPlist *val = mplist (), *pl, *p;
+
+  /* PLIST ::= (sym:VAR mtext:DESCRIPTION TYPE:INIT-VAL ...) ...  */
+  MPLIST_DO (plist, plist)
+    {
+      MSymbol var, type;
+      MText *mt;
+      MPlist *this_val;
+
+      if (! MPLIST_PLIST_P (plist))
+       continue;
+      pl = MPLIST_PLIST (plist);
+      if (! MPLIST_SYMBOL_P (pl))
+       continue;
+      var = MPLIST_SYMBOL (pl);
+      pl = MPLIST_NEXT (pl);
+      mt = get_description_advance (pl);
+      if (! mt || MPLIST_TAIL_P (pl))
+       continue;
+      this_val = mplist ();
+      mplist_add (this_val, Mtext, mt);
+      M17N_OBJECT_UNREF (mt);
+      type = MPLIST_KEY (pl);
+      mplist_add (this_val, type, MPLIST_VAL (pl));
+      MPLIST_DO (pl, MPLIST_NEXT (pl))
+       {
+         if (type != MPLIST_KEY (pl)
+             && (type != Minteger || ! MPLIST_PLIST_P (pl)))
+           break;
+         if (MPLIST_PLIST_P (pl))
+           {
+             MPLIST_DO (p, MPLIST_PLIST (pl))
+               if (! MPLIST_INTEGER_P (p))
+                 break;
+             if (! MPLIST_TAIL_P (p))
+               break;
+           }
+         mplist_add (this_val, MPLIST_KEY (pl), MPLIST_VAL (pl));
+       }
+
+      mplist_put (val, var, this_val);
+    }
+  return val;
+}
+
+
+static MPlist *
+get_variable_list (MSymbol language, MSymbol name)
+{
+  MPlist *per_lang;
+  MPlist *plist, *pl;
+
+  if (language == Mnil || name == Mnil)
+    MERROR (MERROR_IM, NULL);
+  if (! variable_list)
+    variable_list = mplist ();
+  per_lang = mplist_get (variable_list, language);
+  if (per_lang)
+    {
+      plist = mplist_find_by_key (per_lang, name);
+      if (plist)
+       return (MPLIST_VAL (plist));
+    }
+  else
+    {
+      per_lang = mplist ();
+      mplist_add (variable_list, language, per_lang);
+    }
+  plist = load_im_info (language, name, M_variable);
+  if (! plist || mplist_key (plist) == Mnil)
+    {
+      if (! plist)
+       plist = mplist ();
+      mplist_add (per_lang, name, plist);
+      return plist;
+    }
+  pl = parse_variable_list (mplist_value (plist));
+  M17N_OBJECT_UNREF (plist);
+  mplist_put (per_lang, name, pl);
+  return pl;
+}
+
+static void
+input_method_hook (MSymbol tag0, MSymbol tag1, MSymbol tag2, MSymbol tag3)
+{
+  MPlist *plist, *pl, *p;
+  char path[PATH_MAX];
+
+  /* Cancel the hook.  */
+  msymbol_put (tag0, M_database_hook, NULL);
+  tag3 = Mnil;
+
+  mplist_push (load_im_info_keys, M_description, Mt);
+  MPLIST_DO (plist, mdatabase__dir_list)
+    {
+      char *dirname = (char *) MPLIST_VAL (plist);
+      int dirlen;
+      DIR *dir = opendir (dirname);
+      struct dirent *dp;
+
+      if (! dir)
+       continue;
+      dirlen = strlen (dirname);
+      strcpy (path, dirname);
+      while ((dp = readdir (dir)) != NULL)
+       {
+         /* We can't trust dp->d_nameln.  */
+         int len = strlen (dp->d_name);
+         FILE *fp;
+
+         if (len > 4 && memcmp (dp->d_name + len - 4, ".mim", 4) == 0)
+           {
+             strcpy (path + dirlen, dp->d_name);
+             fp = fopen (path, "r");
+             if (! fp)
+               continue;
+             pl = mplist__from_file (fp, load_im_info_keys);
+             fclose (fp);
+             if (pl)
+               {
+                 if (MPLIST_PLIST_P (pl))
+                   {
+                     p = MPLIST_PLIST (pl);
+                     p = MPLIST_NEXT (p);
+                     if (MPLIST_SYMBOL_P (p))
+                       {
+                         tag1 = MPLIST_VAL (p);
+                         p = MPLIST_NEXT (p);
+                         if (MPLIST_SYMBOL_P (p))
+                           {
+                             tag2 = MPLIST_VAL (p);
+                             mdatabase_define (tag0, tag1, tag2, tag3,
+                                               NULL, path);
+                           }
+                       }
+                   }
+                 M17N_OBJECT_UNREF (pl);
+               }
+           }
+       }
+      closedir (dir);
+    }
+  mplist_pop (load_im_info_keys);
+}
+
+
 /* Support functions for mdebug_dump_im.  */
 
 static void
@@ -1809,8 +2214,10 @@ minput__init ()
        NULL, NULL, NULL, "Escape", NULL, NULL, NULL, NULL };
   char buf[6], buf2[256];
   int i;
+  MPlist *plist;
 
   Minput_method = msymbol ("input-method");
+  msymbol_put (Minput_method, M_database_hook, (void *) input_method_hook);
   Minput_driver = msymbol ("input-driver");
   Mtitle = msymbol ("title");
   Mmacro = msymbol ("macro");
@@ -1847,6 +2254,9 @@ minput__init ()
   Minput_candidates_done = msymbol ("input-candidates-done");
   Minput_candidates_draw = msymbol ("input-candidates-draw");
   Minput_set_spot = msymbol ("input-set-spot");
+  Minput_focus_move = msymbol ("input-focus-move");
+  Minput_focus_in = msymbol ("input-focus-in");
+  Minput_focus_out = msymbol ("input-focus-out");
   Minput_toggle = msymbol ("input-toggle");
   Minput_reset = msymbol ("input-reset");
 
@@ -1857,6 +2267,17 @@ minput__init ()
   Mfini = msymbol ("fini");
 
   M_key_alias = msymbol ("  key-alias");
+  M_description = msymbol ("description");
+  M_command = msymbol ("command");
+  M_variable = msymbol ("variable");
+
+  Mdetail_text = msymbol_as_managing_key ("  detail-text");
+
+  load_im_info_keys = mplist ();
+  plist = mplist_add (load_im_info_keys, Mmap, Mnil);
+  plist = mplist_add (plist, Mstate, Mnil);
+  plist = mplist_add (plist, Mmacro, Mnil);
+  plist = mplist_add (plist, Mmodule, Mnil);
 
   buf[0] = 'C';
   buf[1] = '-';
@@ -1888,6 +2309,8 @@ minput__init ()
     one_char_symbol[i] = msymbol (buf + 2);
   one_char_symbol[i] = msymbol ("M-Delete");
 
+  command_list = variable_list = NULL;
+
   minput_default_driver.open_im = open_im;
   minput_default_driver.close_im = close_im;
   minput_default_driver.create_ic = create_ic;
@@ -1904,6 +2327,39 @@ minput__init ()
 void
 minput__fini ()
 {
+  MPlist *par_lang, *par_im, *p;
+
+  if (command_list)
+    {
+      MPLIST_DO (par_lang, command_list)
+       {
+         MPLIST_DO (par_im, MPLIST_VAL (par_lang))
+           {
+             MPLIST_DO (p, MPLIST_VAL (par_im))
+               M17N_OBJECT_UNREF (MPLIST_VAL (p));
+             M17N_OBJECT_UNREF (MPLIST_VAL (par_im));
+           }
+         M17N_OBJECT_UNREF (MPLIST_VAL (par_lang));
+       }
+      M17N_OBJECT_UNREF (command_list);
+      command_list = NULL;
+    }
+  if (variable_list)
+    {
+      MPLIST_DO (par_lang, variable_list)
+       {
+         MPLIST_DO (par_im, MPLIST_VAL (par_lang))
+           {
+             MPLIST_DO (p, MPLIST_VAL (par_im))
+               M17N_OBJECT_UNREF (MPLIST_VAL (p));
+             M17N_OBJECT_UNREF (MPLIST_VAL (par_im));
+           }
+         M17N_OBJECT_UNREF (MPLIST_VAL (par_lang));
+       }
+      M17N_OBJECT_UNREF (variable_list);
+      variable_list = NULL;
+    }
+
   if (minput_default_driver.callback_list)
     {
       M17N_OBJECT_UNREF (minput_default_driver.callback_list);
@@ -1914,6 +2370,8 @@ minput__fini ()
       M17N_OBJECT_UNREF (minput_driver->callback_list);
       minput_driver->callback_list = NULL;
     }
+
+  M17N_OBJECT_UNREF (load_im_info_keys);
 }
 
 void
@@ -1958,8 +2416,8 @@ minput__char_to_key (int c)
 /***ja
     @name ÊÑ¿ô¡§ ¥³¡¼¥ë¥Ð¥Ã¥¯¥³¥Þ¥ó¥ÉÍÑÄêµÁºÑ¤ß¥·¥ó¥Ü¥ë.
 
-    ÆþÎϥ᥽¥Ã¥É¥É¥é¥¤¥Ð¤Î¥³¡¼¥ë¥Ð¥Ã¥¯´Ø¿ô¤Ë¤ª¤¤¤Æ @c COMMAND °ú¿ô¤È¤·
-    ¤ÆÍѤ¤¤é¤ì¤ëÄêµÁºÑ¤ß¥·¥ó¥Ü¥ë (#MInputDriver::callback_list »²¾È)¡£
+    ÆþÎϥ᥽¥Ã¥É¥É¥é¥¤¥Ð¤Î¥³¡¼¥ë¥Ð¥Ã¥¯´Ø¿ô¤Ë¤ª¤¤¤Æ @c COMMAND 
+    °ú¿ô¤È¤·¤ÆÍѤ¤¤é¤ì¤ëÄêµÁºÑ¤ß¥·¥ó¥Ü¥ë (#MInputDriver::callback_list »²¾È)¡£
       */ 
 /*** @{ */ 
 /*=*/
@@ -1974,9 +2432,13 @@ MSymbol Minput_candidates_start;
 MSymbol Minput_candidates_done;
 MSymbol Minput_candidates_draw;
 MSymbol Minput_set_spot;
+MSymbol Minput_focus_move;
+MSymbol Minput_focus_in;
+MSymbol Minput_focus_out;
 MSymbol Minput_toggle;
 MSymbol Minput_reset;
 /*** @} */
+
 /*=*/
 
 /***en
@@ -2004,20 +2466,19 @@ MSymbol Minput_reset;
 /***ja
     @brief ÆâÉôÆþÎϥ᥽¥Ã¥ÉÍѥǥե©¥ë¥È¥É¥é¥¤¥Ð.
 
-    ÆþÎϥɥ饤¥Ð #minput_default_driver ¤ÏÆâÉôÆþÎϥ᥽¥Ã¥ÉÍѤΥǥե©¥ë
-    ¥È¤Î¥É¥é¥¤¥Ð¤Ç¤¢¤ë¡£
+    ÊÑ¿ô #minput_default_driver ¤ÏÆâÉôÆþÎϥ᥽¥Ã¥ÉÍѤΥǥե©¥ë¥È¤Î¥É¥é¥¤¥Ð¤òɽ¤¹¡£
 
     ¥á¥ó¥Ð MInputDriver::open_im () ¤Ï m17n ¥Ç¡¼¥¿¥Ù¡¼¥¹Ã椫¤é¥¿¥° 
-    \< #Minput_method, $LANGUAGE, $NAME\> ¤Ë¹çÃפ¹¤ëÆþÎϥ᥽¥Ã¥É¤òõ¤·¡¢
-    ¤½¤ì¤ò¥í¡¼¥É¤¹¤ë¡£
+    \< #Minput_method, $LANGUAGE, $NAME\> 
+    ¤Ë¹çÃפ¹¤ëÆþÎϥ᥽¥Ã¥É¤òõ¤·¡¢¤½¤ì¤ò¥í¡¼¥É¤¹¤ë¡£
 
-    ¥á¥ó¥Ð MInputDriver::callback_list () ¤Ï @c NULL ¤Ê¤Î¤Ç¡¢¥×¥í¥°¥é
-    ¥Þ¦¤ÇÀÕǤ¤ò»ý¤Ã¤Æ, Å¬Àڤʥ³¡¼¥ë¥Ð¥Ã¥¯´Ø¿ô¤Î plist ¤ËÀßÄꤷ¤Ê¤¯¤Æ
-    ¤Ï¤Ê¤é¤Ê¤¤¡£¤µ¤â¤Ê¤¤¤È¡¢preedit ¥Æ¥­¥¹¥È¤Ê¤É¤Î¥Õ¥£¡¼¥É¥Ð¥Ã¥¯¾ðÊó¤¬
-    ¥æ¡¼¥¶¤Ëɽ¼¨¤µ¤ì¤Ê¤¤¡£
+    ¥á¥ó¥Ð MInputDriver::callback_list () ¤Ï @c NULL ¤Ç¤¢¤ê¡¢
+    ¤·¤¿¤¬¤Ã¤Æ¡¢¥×¥í¥°¥é¥Þ¦¤ÇÀÕǤ¤ò»ý¤Ã¤Æ Å¬Àڤʥ³¡¼¥ë¥Ð¥Ã¥¯´Ø¿ô¤Î plist
+    ¤ËÀßÄꤷ¤Ê¤¯¤Æ¤Ï¤Ê¤é¤Ê¤¤¡£¤µ¤â¤Ê¤¤¤È¡¢preedit 
+    ¥Æ¥­¥¹¥È¤Ê¤É¤Î¥Õ¥£¡¼¥É¥Ð¥Ã¥¯¾ðÊ󤬥桼¥¶¤Ëɽ¼¨¤µ¤ì¤Ê¤¤¡£
 
-    ¥Þ¥¯¥í M17N_INIT () ¤ÏÊÑ¿ô #minput_driver ¤ò¤³¤Î¥É¥é¥¤¥Ð¤Ø¤Î¥Ý¥¤¥ó
-    ¥¿¤ËÀßÄꤷ¡¢Á´¤Æ¤ÎÆâÉôÆþÎϥ᥽¥Ã¥É¤¬¤³¤Î¥É¥é¥¤¥Ð¤ò»È¤¦¤è¤¦¤Ë¤¹¤ë¡£
+    ¥Þ¥¯¥í M17N_INIT () ¤ÏÊÑ¿ô #minput_driver 
+    ¤ò¤³¤Î¥É¥é¥¤¥Ð¤Ø¤Î¥Ý¥¤¥ó¥¿¤ËÀßÄꤷ¡¢Á´¤Æ¤ÎÆâÉôÆþÎϥ᥽¥Ã¥É¤¬¤³¤Î¥É¥é¥¤¥Ð¤ò»È¤¦¤è¤¦¤Ë¤¹¤ë¡£
 
     ¤·¤¿¤¬¤Ã¤Æ¡¢@c minput_driver ¤¬¥Ç¥Õ¥©¥ë¥ÈÃͤΤޤޤǤ¢¤ì¤Ð¡¢minput_ 
     ¤Ç»Ï¤Þ¤ë´Ø¿ô¤Î¥É¥é¥¤¥Ð¤Ë°Í¸¤¹¤ë°ú¿ô $ARG ¤Ï¤¹¤Ù¤Æ̵»ë¤µ¤ì¤ë¡£  */
@@ -2031,15 +2492,14 @@ MInputDriver minput_default_driver;
     The variable #minput_driver is a pointer to the input method
     driver that is used by internal input methods.  The macro
     M17N_INIT () initializes it to a pointer to #minput_default_driver
-    (if <m17n.h> is included) or to #minput_gui_driver (if
-    <m17n-gui.h> is included).  */ 
+    if <m17n<EM></EM>.h> is included.  */ 
 /***ja
     @brief ÆâÉôÆþÎϥ᥽¥Ã¥ÉÍѥɥ饤¥Ð.
 
     ÊÑ¿ô #minput_driver ¤ÏÆâÉôÆþÎϥ᥽¥Ã¥É¤Ë¤è¤Ã¤Æ»ÈÍѤµ¤ì¤Æ¤¤¤ëÆþÎÏ¥á
-    ¥½¥Ã¥É¥É¥é¥¤¥Ð¤Ø¤Î¥Ý¥¤¥ó¥¿¤Ç¤¢¤ë¡£¥Þ¥¯¥íM17N_INIT () ¤Ï¤³¤Î¥Ý¥¤¥ó
-    ¥¿¤ò #minput_default_driver (<m17n.h> ¤¬´Þ¤Þ¤ì¤ë»þ) ¤Þ¤¿¤Ï 
-    #minput_gui_driver ( <m17n-gui.h> ¤¬´Þ¤Þ¤ì¤ë»þ) ¤Ë½é´ü²½¤¹¤ë¡£  */ 
+    ¥½¥Ã¥É¥É¥é¥¤¥Ð¤Ø¤Î¥Ý¥¤¥ó¥¿¤Ç¤¢¤ë¡£¥Þ¥¯¥í M17N_INIT () ¤Ï¤³¤Î¥Ý¥¤¥ó
+    ¥¿¤ò#minput_default_driver (<m17n<EM></EM>.h> ¤¬ include ¤µ¤ì¤Æ¤¤¤ë
+    »þ) ¤Ë½é´ü²½¤¹¤ë¡£  */ 
 
 MInputDriver *minput_driver;
 
@@ -2073,24 +2533,21 @@ MSymbol Minput_driver;
 /***ja
     @brief ÆþÎϥ᥽¥Ã¥É¤ò¥ª¡¼¥×¥ó¤¹¤ë.
 
-    ´Ø¿ô minput_open_im () ¤Ï¸À¸ì $LANGUAGE ¤È̾Á° $NAME ¤Ë¹çÃפ¹¤ëÆþ
-    Îϥ᥽¥Ã¥É¤ò¥ª¡¼¥×¥ó¤·¡¢¿·¤¿¤Ë³ä¤êÅö¤Æ¤é¤ì¤¿ÆþÎϥ᥽¥Ã¥É¥ª¥Ö¥¸¥§¥¯
-    ¥È¤Ø¤Î¥Ý¥¤¥ó¥¿¤òÊÖ¤¹¡£
+    ´Ø¿ô minput_open_im () ¤Ï¸À¸ì $LANGUAGE ¤È̾Á° $NAME 
+    ¤Ë¹çÃפ¹¤ëÆþÎϥ᥽¥Ã¥É¤ò¥ª¡¼¥×¥ó¤·¡¢¿·¤¿¤Ë³ä¤êÅö¤Æ¤é¤ì¤¿ÆþÎϥ᥽¥Ã¥É¥ª¥Ö¥¸¥§¥¯¥È¤Ø¤Î¥Ý¥¤¥ó¥¿¤òÊÖ¤¹¡£
     
     ¤³¤Î´Ø¿ô¤Ï¡¢¤Þ¤ºÆþÎϥ᥽¥Ã¥ÉÍѤΥɥ饤¥Ð¤ò°Ê²¼¤Î¤è¤¦¤Ë¤·¤Æ·èÄꤹ¤ë¡£
 
-    $LANGUAGE ¤¬ #Mnil ¤Ç¤Ê¤±¤ì¤Ð¡¢ÊÑ¿ô #minput_driver ¤Ç»Ø¤µ¤ì¤Æ¤¤¤ë
-    ¥É¥é¥¤¥Ð¤òÍѤ¤¤ë¡£
+    $LANGUAGE ¤¬ #Mnil ¤Ç¤Ê¤±¤ì¤Ð¡¢ÊÑ¿ô #minput_driver 
+    ¤Ç»Ø¤µ¤ì¤Æ¤¤¤ë¥É¥é¥¤¥Ð¤òÍѤ¤¤ë¡£
 
-    $LANGUAGE ¤¬ #Mnil ¤Ç¤¢¤ê¡¢$NAME ¤¬ #Minput_driver ¥×¥í¥Ñ¥Æ¥£¤ò»ý
-    ¤Ä¾ì¹ç¤Ë¤Ï¡¢¤½¤Î¥×¥í¥Ñ¥Æ¥£¤ÎÃͤǻؤµ¤ì¤Æ¤¤¤ëÆþÎϥɥ饤¥Ð¤òÍѤ¤¤ÆÆþ
-    Îϥ᥽¥Ã¥É¤ò¥ª¡¼¥×¥ó¤¹¤ë¡£$NAME ¤Ë¤½¤Î¤è¤¦¤Ê¥×¥í¥Ñ¥Æ¥£¤¬Ìµ¤«¤Ã¤¿¾ì
-    ¹ç¤Ï @c NULL ¤òÊÖ¤¹¡£
+    $LANGUAGE ¤¬ #Mnil ¤Ç¤¢¤ê¡¢$NAME ¤¬ #Minput_driver
+    ¥×¥í¥Ñ¥Æ¥£¤ò»ý¤Ä¾ì¹ç¤Ë¤Ï¡¢¤½¤Î¥×¥í¥Ñ¥Æ¥£¤ÎÃͤǻؤµ¤ì¤Æ¤¤¤ëÆþÎϥɥ饤¥Ð¤òÍѤ¤¤ÆÆþÎϥ᥽¥Ã¥É¤ò¥ª¡¼¥×¥ó¤¹¤ë¡£
+    $NAME ¤Ë¤½¤Î¤è¤¦¤Ê¥×¥í¥Ñ¥Æ¥£¤¬Ìµ¤«¤Ã¤¿¾ì¹ç¤Ï @c NULL ¤òÊÖ¤¹¡£
 
     ¼¡¤¤¤Ç¡¢¥É¥é¥¤¥Ð¤Î¥á¥ó¥Ð MInputDriver::open_im () ¤¬¸Æ¤Ð¤ì¤ë¡£
 
-    $ARG ¤Ï¡¢¥É¥é¥¤¥Ð¤¬»²¾È¤Ç¤­¤ë¤è¤¦¤Ë¡¢¹½Â¤ÂΠMInputMethod ¤Î¥á¥ó¥Ð 
-    @c arg ¤ËÀßÄꤵ¤ì¤ë¡£
+    $ARG ¤Ï¹½Â¤ÂΠMInputMethod ¤Î¥á¥ó¥Ð @c arg ¤ËÀßÄꤵ¤ì¡¢¥É¥é¥¤¥Ð¤«¤é»²¾È¤Ç¤­¤ë¡£
 
     @latexonly \IPAlabel{minput_open} @endlatexonly
 
@@ -2102,6 +2559,8 @@ minput_open_im (MSymbol language, MSymbol name, void *arg)
   MInputMethod *im;
   MInputDriver *driver;
 
+  MDEBUG_PRINT2 ("  [IM] opening (%s %s) ... ",
+        msymbol_name (language), msymbol_name (name));
   if (language)
     driver = minput_driver;
   else
@@ -2118,9 +2577,11 @@ minput_open_im (MSymbol language, MSymbol name, void *arg)
   im->driver = *driver;
   if ((*im->driver.open_im) (im) < 0)
     {
+      MDEBUG_PRINT (" failed\n");
       free (im);
       return NULL;
     }
+  MDEBUG_PRINT (" ok\n");
   return im;
 }
 
@@ -2135,15 +2596,17 @@ minput_open_im (MSymbol language, MSymbol name, void *arg)
 /***ja
     @brief ÆþÎϥ᥽¥Ã¥É¤ò¥¯¥í¡¼¥º¤¹¤ë.
 
-    ´Ø¿ô minput_close_im () ¤Ï¡¢ÆþÎϥ᥽¥Ã¥É $IM ¤ò¥¯¥í¡¼¥º¤¹¤ë¡£¤³¤Î
-    ÆþÎϥ᥽¥Ã¥É $IM ¤Ï minput_open_im () ¤Ë¤è¤Ã¤Æºî¤é¤ì¤¿¤â¤Î¤Ç¤Ê¤±¤ì
-    ¤Ð¤Ê¤é¤Ê¤¤¡£  */
+    ´Ø¿ô minput_close_im () ¤Ï¡¢ÆþÎϥ᥽¥Ã¥É $IM ¤ò¥¯¥í¡¼¥º¤¹¤ë¡£
+    ¤³¤ÎÆþÎϥ᥽¥Ã¥É $IM ¤Ï minput_open_im () ¤Ë¤è¤Ã¤Æºî¤é¤ì¤¿¤â¤Î¤Ç¤Ê¤±¤ì¤Ð¤Ê¤é¤Ê¤¤¡£  */
 
 void
 minput_close_im (MInputMethod *im)
 {
+  MDEBUG_PRINT2 ("  [IM] closing (%s %s) ... ",
+                msymbol_name (im->name), msymbol_name (im->language));
   (*im->driver.close_im) (im);
   free (im);
+  MDEBUG_PRINT (" done\n");
 }
 
 /*=*/
@@ -2164,15 +2627,15 @@ minput_close_im (MInputMethod *im)
 /***ja
     @brief ÆþÎÏ¥³¥ó¥Æ¥¯¥¹¥È¤òÀ¸À®¤¹¤ë.
 
-    ´Ø¿ô minput_create_ic () ¤ÏÆþÎϥ᥽¥Ã¥É $IM ¤ËÂбþ¤¹¤ëÆþÎÏ¥³¥ó¥Æ¥¯
-    ¥¹¥È¥ª¥Ö¥¸¥§¥¯¥È¤òÀ¸À®¤·¡¢ #Minput_preedit_start,
-    #Minput_status_start, #Minput_status_draw ¤ËÂбþ¤¹¤ë¥³¡¼¥ë¥Ð¥Ã¥¯´Ø
-    ¿ô¤ò¤³¤Î½ç¤Ë¸Æ¤Ö¡£
+    ´Ø¿ô minput_create_ic () ¤ÏÆþÎϥ᥽¥Ã¥É $IM
+    ¤ËÂбþ¤¹¤ëÆþÎÏ¥³¥ó¥Æ¥¯¥¹¥È¥ª¥Ö¥¸¥§¥¯¥È¤òÀ¸À®¤·¡¢
+    #Minput_preedit_start, #Minput_status_start, #Minput_status_draw
+    ¤ËÂбþ¤¹¤ë¥³¡¼¥ë¥Ð¥Ã¥¯´Ø¿ô¤ò¤³¤Î½ç¤Ë¸Æ¤Ö¡£
 
     @return
 
-    ÆþÎÏ¥³¥ó¥Æ¥¯¥¹¥È¤¬À¸À®¤µ¤ì¤¿¾ì¹ç¡¢minput_create_ic () ¤Ï¤½¤ÎÆþÎÏ¥³
-    ¥ó¥Æ¥¯¥¹¥È¤Ø¤Î¥Ý¥¤¥ó¥¿¤òÊÖ¤¹¡£¼ºÇÔ¤·¤¿¾ì¹ç¤Ï @c NULL ¤òÊÖ¤¹¡£
+    ÆþÎÏ¥³¥ó¥Æ¥¯¥¹¥È¤¬À¸À®¤µ¤ì¤¿¾ì¹ç¡¢minput_create_ic () 
+    ¤Ï¤½¤ÎÆþÎÏ¥³¥ó¥Æ¥¯¥¹¥È¤Ø¤Î¥Ý¥¤¥ó¥¿¤òÊÖ¤¹¡£¼ºÇÔ¤·¤¿¾ì¹ç¤Ï @c NULL ¤òÊÖ¤¹¡£
       */
 
 MInputContext *
@@ -2180,6 +2643,8 @@ minput_create_ic (MInputMethod *im, void *arg)
 {
   MInputContext *ic;
 
+  MDEBUG_PRINT2 ("  [IM] creating context (%s %s) ... ",
+                msymbol_name (im->name), msymbol_name (im->language));
   MSTRUCT_CALLOC (ic, MERROR_IM);
   ic->im = im;
   ic->arg = arg;
@@ -2191,6 +2656,7 @@ minput_create_ic (MInputMethod *im, void *arg)
   ic->plist = mplist ();
   if ((*im->driver.create_ic) (ic) < 0)
     {
+      MDEBUG_PRINT (" failed\n");
       M17N_OBJECT_UNREF (ic->preedit);
       M17N_OBJECT_UNREF (ic->produced);
       M17N_OBJECT_UNREF (ic->plist);
@@ -2205,6 +2671,7 @@ minput_create_ic (MInputMethod *im, void *arg)
       minput__callback (ic, Minput_status_draw);
     }
 
+  MDEBUG_PRINT (" ok\n");
   return ic;
 }
 
@@ -2221,16 +2688,18 @@ minput_create_ic (MInputMethod *im, void *arg)
 /***ja
     @brief ÆþÎÏ¥³¥ó¥Æ¥¯¥¹¥È¤òÇ˲õ¤¹¤ë.
 
-    ´Ø¿ô minput_destroy_ic () ¤Ï¡¢ÆþÎÏ¥³¥ó¥Æ¥¯¥¹¥È $IC ¤òÇ˲õ¤¹¤ë¡£¤³
-    ¤ÎÆþÎÏ¥³¥ó¥Æ¥¯¥¹¥È¤Ï minput_create_ic () ¤Ë¤è¤Ã¤Æºî¤é¤ì¤¿¤â¤Î¤Ç¤Ê
-    ¤±¤ì¤Ð¤Ê¤é¤Ê¤¤¡£¤³¤Î´Ø¿ô¤Ï#Minput_preedit_done,
-    #Minput_status_done, #Minput_candidates_done ¤ËÂбþ¤¹¤ë¥³¡¼¥ë¥Ð¥Ã¥¯´Ø¿ô¤ò
-    ¤³¤Î½ç¤Ë¸Æ¤Ö¡£
+    ´Ø¿ô minput_destroy_ic () ¤Ï¡¢ÆþÎÏ¥³¥ó¥Æ¥¯¥¹¥È $IC ¤òÇ˲õ¤¹¤ë¡£
+    ¤³¤ÎÆþÎÏ¥³¥ó¥Æ¥¯¥¹¥È¤Ï minput_create_ic () 
+    ¤Ë¤è¤Ã¤Æºî¤é¤ì¤¿¤â¤Î¤Ç¤Ê¤±¤ì¤Ð¤Ê¤é¤Ê¤¤¡£¤³¤Î´Ø¿ô¤Ï 
+    #Minput_preedit_done, #Minput_status_done, #Minput_candidates_done 
+    ¤ËÂбþ¤¹¤ë¥³¡¼¥ë¥Ð¥Ã¥¯´Ø¿ô¤ò¤³¤Î½ç¤Ë¸Æ¤Ö¡£
   */
 
 void
 minput_destroy_ic (MInputContext *ic)
 {
+  MDEBUG_PRINT2 ("  [IM] destroying context (%s %s) ... ",
+                msymbol_name (ic->im->name), msymbol_name (ic->im->language));
   if (ic->im->driver.callback_list)
     {
       minput__callback (ic, Minput_preedit_done);
@@ -2241,6 +2710,7 @@ minput_destroy_ic (MInputContext *ic)
   M17N_OBJECT_UNREF (ic->preedit);
   M17N_OBJECT_UNREF (ic->produced);
   M17N_OBJECT_UNREF (ic->plist);
+  MDEBUG_PRINT (" done\n");
   free (ic);
 }
 
@@ -2264,16 +2734,16 @@ minput_destroy_ic (MInputContext *ic)
 /***ja
     @brief ÆþÎÏ¥­¡¼¤ò¥Õ¥£¥ë¥¿¤¹¤ë.
 
-    ´Ø¿ô minput_filter () ¤ÏÆþÎÏ¥­¡¼ $KEY ¤òÆþÎÏ¥³¥ó¥Æ¥¯¥¹¥È $IC ¤Ë±þ
-    ¤¸¤Æ¥Õ¥£¥ë¥¿¤·¡¢preedit ¥Æ¥­¥¹¥È¡¢¥¹¥Æ¡¼¥¿¥¹¡¢¸½»þÅÀ¤Ç¤Î¸õÊ䤬ÊѲ½
-    ¤·¤¿ºÝ¤Ë¤Ï¤½¤ì¤¾¤ì#Minput_preedit_draw, #Minput_status_draw,
+    ´Ø¿ô minput_filter () ¤ÏÆþÎÏ¥­¡¼ $KEY ¤òÆþÎÏ¥³¥ó¥Æ¥¯¥¹¥È $IC 
+    ¤Ë±þ¤¸¤Æ¥Õ¥£¥ë¥¿¤·¡¢preedit ¥Æ¥­¥¹¥È¡¢¥¹¥Æ¡¼¥¿¥¹¡¢¸½»þÅÀ¤Ç¤Î¸õÊ䤬ÊѲ½¤·¤¿»þÅÀ¤Ç¡¢¤½¤ì¤¾¤ì
+    #Minput_preedit_draw, #Minput_status_draw,
     #Minput_candidates_draw ¤ËÂбþ¤¹¤ë¥³¡¼¥ë¥Ð¥Ã¥¯´Ø¿ô¤ò¸Æ¤Ö¡£
 
     @return 
-    $KEY ¤¬¥Õ¥£¥ë¥¿¤µ¤ì¤ì¤Ð¡¢¤³¤Î´Ø¿ô¤Ï 1 ¤òÊÖ¤¹¡£¤³¤Î¾ì¹ç¸Æ¤Ó
-    ½Ð¤·Â¦¤Ï¤³¤Î¥­¡¼¤ò¼Î¤Æ¤ë¤Ù¤­¤Ç¤¢¤ë¡£¤½¤¦¤Ç¤Ê¤±¤ì¤Ð 0 ¤òÊÖ¤·¡¢¸Æ¤Ó
-    ½Ð¤·Â¦¤Ï¡¢¤¿¤È¤¨¤ÐƱ¤¸¥­¡¼¤Ç´Ø¿ô minput_lookup () ¤ò¸Æ¤Ö¤Ê¤É¤·¤Æ¡¢
-    ¤³¤Î¥­¡¼¤ò½èÍý¤¹¤ë¡£
+    $KEY ¤¬¥Õ¥£¥ë¥¿¤µ¤ì¤ì¤Ð¡¢¤³¤Î´Ø¿ô¤Ï 1 ¤òÊÖ¤¹¡£
+    ¤³¤Î¾ì¹ç¸Æ¤Ó½Ð¤·Â¦¤Ï¤³¤Î¥­¡¼¤ò¼Î¤Æ¤ë¤Ù¤­¤Ç¤¢¤ë¡£
+    ¤½¤¦¤Ç¤Ê¤±¤ì¤Ð 0 ¤òÊÖ¤·¡¢¸Æ¤Ó½Ð¤·Â¦¤Ï¡¢¤¿¤È¤¨¤ÐƱ¤¸¥­¡¼¤Ç´Ø¿ô minput_lookup ()
+    ¤ò¸Æ¤Ö¤Ê¤É¤·¤Æ¡¢¤³¤Î¥­¡¼¤ò½èÍý¤¹¤ë¡£
 
     @latexonly \IPAlabel{minput_filter} @endlatexonly
 */
@@ -2297,7 +2767,6 @@ minput_filter (MInputContext *ic, MSymbol key, void *arg)
       if (ic->candidates_changed)
        minput__callback (ic, Minput_candidates_draw);
     }
-  ic->preedit_changed = ic->status_changed = ic->candidates_changed = 0;
 
   return ret;
 }
@@ -2305,7 +2774,7 @@ minput_filter (MInputContext *ic, MSymbol key, void *arg)
 /*=*/
 
 /***en
-    @brief Lookup a text produced in the input context.
+    @brief Look up a text produced in the input context.
 
     The minput_lookup () function looks up a text in the input context
     $IC.  $KEY must be the same one provided to the previous call of
@@ -2322,11 +2791,10 @@ minput_filter (MInputContext *ic, MSymbol key, void *arg)
     may be produced in $MT.  */
 
 /***ja
-    @brief ÆþÎÏ¥³¥ó¥Æ¥¯¥¹¥ÈÃæ¤Î¥Æ¥­¥¹¥È¤Î¸¡º÷.
+    @brief ÆþÎÏ¥³¥ó¥Æ¥¯¥¹¥ÈÃæ¤Î¥Æ¥­¥¹¥È¤òõ¤¹.
 
-    ´Ø¿ô minput_lookup () ¤ÏÆþÎÏ¥³¥ó¥Æ¥¯¥¹¥È $IC Ãæ¤Î¥Æ¥­¥¹¥È¤ò¸¡º÷¤¹
-    ¤ë¡£$KEY ¤Ï´Ø¿ôminput_filter () ¤Ø¤ÎľÁ°¤Î¸Æ¤Ó½Ð¤·¤ËÍѤ¤¤é¤ì¤¿¤â¤Î
-    ¤ÈƱ¤¸¤Ç¤Ê¤¯¤Æ¤Ï¤Ê¤é¤Ê¤¤¡£
+    ´Ø¿ô minput_lookup () ¤ÏÆþÎÏ¥³¥ó¥Æ¥¯¥¹¥È $IC Ãæ¤Î¥Æ¥­¥¹¥È¤òõ¤¹¡£
+    $KEY ¤Ï´Ø¿ô minput_filter () ¤Ø¤ÎľÁ°¤Î¸Æ¤Ó½Ð¤·¤ËÍѤ¤¤é¤ì¤¿¤â¤Î¤ÈƱ¤¸¤Ç¤Ê¤¯¤Æ¤Ï¤Ê¤é¤Ê¤¤¡£
 
     ¥Æ¥­¥¹¥È¤¬ÆþÎϥ᥽¥Ã¥É¤Ë¤è¤Ã¤ÆÀ¸À®¤µ¤ì¤Æ¤¤¤ì¤Ð¡¢¥Æ¥­¥¹¥È¤Ï M-text
     $MT ¤ËÏ¢·ë¤µ¤ì¤ë¡£
@@ -2335,8 +2803,8 @@ minput_filter (MInputContext *ic, MSymbol key, void *arg)
 
     @return 
     $KEY ¤¬ÆþÎϥ᥽¥Ã¥É¤Ë¤è¤Ã¤ÆŬÀڤ˽èÍý¤Ç¤­¤ì¤Ð¡¢¤³¤Î´Ø¿ô¤Ï 0 ¤òÊÖ¤¹¡£
-    ¤½¤¦¤Ç¤Ê¤±¤ì¤Ð -1 ¤òÊÖ¤¹¡£¤³¤Î¾ì¹ç¤Ç¤â $MT ¤Ë²¿¤é¤«¤Î¥Æ¥­¥¹¥È¤¬À¸
-    À®¤µ¤ì¤Æ¤¤¤ë¤³¤È¤¬¤¢¤ë¡£
+    ¤½¤¦¤Ç¤Ê¤±¤ì¤Ð -1 ¤òÊÖ¤¹¡£
+    ¤³¤Î¾ì¹ç¤Ç¤â $MT ¤Ë²¿¤é¤«¤Î¥Æ¥­¥¹¥È¤¬À¸À®¤µ¤ì¤Æ¤¤¤ë¤³¤È¤¬¤¢¤ë¡£
 
     @latexonly \IPAlabel{minput_lookup} @endlatexonly  */
 
@@ -2351,39 +2819,40 @@ minput_lookup (MInputContext *ic, MSymbol key, void *arg, MText *mt)
     @brief Set the spot of the input context.
 
     The minput_set_spot () function set the spot of input context $IC
-    to coordinate ($X, $Y ) with the height $ASCENT and $DESCENT .
+    to coordinate ($X, $Y ) with the height specified by $ASCENT and $DESCENT .
     The semantics of these values depend on the input method driver.
-    $FONTSIZE specfies the fontsize of a preedit text in 1/10 point.
 
-    For instance, an driver designed to work in CUI environment may
+    For instance, a driver designed to work in a CUI environment may
     use $X and $Y as column and row numbers, and ignore $ASCENT and
-    $DESCENT .  An driver designed to work on a window system may
-    treat $X and $Y as pixel offsets relative to the origin of the
-    client window, and treat $ASCENT and $DESCENT as ascent and
-    descent pixels of a line at ($X . $Y ).
+    $DESCENT .  A driver designed to work in a window system may
+    interpret $X and $Y as pixel offsets relative to the origin of the
+    client window, and may interpret $ASCENT and $DESCENT as the ascent- and
+    descent pixels of the line at ($X . $Y ).
+
+    $FONTSIZE specifies the fontsize of preedit text in 1/10 point.
 
-    $MT and $POS is an M-text and a character position at the spot.
+    $MT and $POS is the M-text and the character position at the spot.
     $MT may be @c NULL, in which case, the input method cannot get
     information about the text around the spot.  */
 
 /***ja
-    @brief ÆþÎÏ¥³¥ó¥Æ¥¯¥¹¥È¤Î¥¹¥Ý¥Ã¥È¤òÀßÄꤹ¤ë
+    @brief ÆþÎÏ¥³¥ó¥Æ¥¯¥¹¥È¤Î¥¹¥Ý¥Ã¥È¤òÀßÄꤹ¤ë.
 
-    ´Ø¿ô minput_set_spot () ¤Ï¡¢ÆþÎÏ¥³¥ó¥Æ¥¯¥¹¥È $IC ¤Î¥¹¥Ý¥Ã¥È¤ò¡¢ºÂ
-    É¸ ($X, $Y )¤Ë ¡¢¹â¤µ $ASCENT¡¢ $DESCENT ¤ÇÀßÄꤹ¤ë¡£ ¤³¤ì¤é¤ÎÃͤÎ
-    °ÕÌ£¤ÏÆþÎϥ᥽¥Ã¥É¥É¥é¥¤¥Ð¤Ë°Í¸¤¹¤ë¡£$FONTSIZE ¤Ïpreedit ¥Æ¥­¥¹¥È
-    ¤Î¥Õ¥©¥ó¥È¥µ¥¤¥º¤ò 1/10 ¥Ý¥¤¥ó¥Èñ°Ì¤Ç»ØÄꤹ¤ë¡£
+    ´Ø¿ô minput_set_spot () ¤Ï¡¢ÆþÎÏ¥³¥ó¥Æ¥¯¥¹¥È $IC ¤Î¥¹¥Ý¥Ã¥È¤ò¡¢ºÂɸ ($X, $Y )
+    ¤Î°ÌÃ֤ˠ¡¢¹â¤µ $ASCENT¡¢ $DESCENT 
+    ¤ÇÀßÄꤹ¤ë¡£ ¤³¤ì¤é¤ÎÃͤΰÕÌ£¤ÏÆþÎϥ᥽¥Ã¥É¥É¥é¥¤¥Ð¤Ë°Í¸¤¹¤ë¡£
 
-    ¤¿¤È¤¨¤Ð CUI ´Ä¶­¤ÇÆ°ºî¤¹¤ë¥É¥é¥¤¥Ð¤Ï $X ¤È $Y ¤ò¤½¤ì¤¾¤ìÎó¤È¹Ô¤Î
-    ÈÖ¹æ¤È¤·¤ÆÍѤ¤¡¢$ASCENT ¤È $DESCENT ¤ò̵»ë¤¹¤ë¤«¤â¤·¤ì¤Ê¤¤¡£ ¤Þ¤¿
-    ¥¦¥£¥ó¥É¥¦¥·¥¹¥Æ¥àÍѤΥɥ饤¥Ð¤Ï $X ¤È $Y ¤ò¥¯¥é¥¤¥¢¥ó¥È¥¦¥£¥ó¥É¥¦
-    ¤Î¸¶ÅÀ¤«¤é¤Î¥ª¥Õ¥»¥Ã¥È¤ò¥Ô¥¯¥»¥ëñ°Ì¤Çɽ¤·¤¿¤â¤Î¤È¤·¤Æ°·¤¤¡¢
-    $ASCENT ¤È $DESCENT ¤ò ($X . $Y ) ¤ÎÎó¤Î¥¢¥»¥ó¥È¤È¥Ç¥£¥»¥ó¥È¤ò¥Ô¥¯
-    ¥»¥ëñ°Ì¤Çɽ¤·¤¿¤â¤Î¤È¤·¤Æ°·¤¦¤«¤â¤·¤ì¤Ê¤¤¡£
+    ¤¿¤È¤¨¤Ð CUI ´Ä¶­¤ÇÆ°ºî¤¹¤ë¥É¥é¥¤¥Ð¤Ï $X ¤È $Y 
+    ¤ò¤½¤ì¤¾¤ìÎó¤È¹Ô¤ÎÈÖ¹æ¤È¤·¤ÆÍѤ¤¡¢$ASCENT ¤È $DESCENT 
+    ¤ò̵»ë¤¹¤ë¤«¤â¤·¤ì¤Ê¤¤¡£ ¤Þ¤¿¥¦¥£¥ó¥É¥¦¥·¥¹¥Æ¥àÍѤΥɥ饤¥Ð¤Ï
+    $X ¤È $Y ¤ò¥¯¥é¥¤¥¢¥ó¥È¥¦¥£¥ó¥É¥¦¤Î¸¶ÅÀ¤«¤é¤Î¥ª¥Õ¥»¥Ã¥È¤ò¥Ô¥¯¥»¥ëñ°Ì¤Çɽ¤·¤¿¤â¤Î¤È¤·¤Æ°·¤¤¡¢
+    $ASCENT ¤È $DESCENT ¤ò ($X . $Y )
+    ¤ÎÎó¤Î¥¢¥»¥ó¥È¤È¥Ç¥£¥»¥ó¥È¤ò¥Ô¥¯¥»¥ëñ°Ì¤Çɽ¤·¤¿¤â¤Î¤È¤·¤Æ°·¤¦¤«¤â¤·¤ì¤Ê¤¤¡£
+
+    $FONTSIZE ¤Ë¤Ï preedit ¥Æ¥­¥¹¥È¤Î¥Õ¥©¥ó¥È¥µ¥¤¥º¤ò 1/10 ¥Ý¥¤¥ó¥Èñ°Ì¤Ç»ØÄꤹ¤ë¡£
 
     $MT ¤È $POS ¤Ï¤½¤Î¥¹¥Ý¥Ã¥È¤Î M-text ¤Èʸ»ú°ÌÃ֤Ǥ¢¤ë¡£$MT ¤Ï @c
-    NULL ¤Ç¤â¤è¤¯¡¢¤½¤Î¾ì¹ç¤Ë¤ÏÆþÎϥ᥽¥Ã¥É¤Ï¥¹¥Ý¥Ã¥È¼þÊդΥƥ­¥¹¥È¤Ë
-    ´Ø¤¹¤ë¾ðÊó¤òÆÀ¤ë¤³¤È¤¬¤Ç¤­¤Ê¤¤¡£
+    NULL ¤Ç¤â¤è¤¯¡¢¤½¤Î¾ì¹ç¤Ë¤ÏÆþÎϥ᥽¥Ã¥É¤Ï¥¹¥Ý¥Ã¥È¼þÊդΥƥ­¥¹¥È¤Ë´Ø¤¹¤ë¾ðÊó¤òÆÀ¤ë¤³¤È¤¬¤Ç¤­¤Ê¤¤¡£
     */
 
 void
@@ -2407,12 +2876,12 @@ minput_set_spot (MInputContext *ic, int x, int y,
     @brief Toggle input method.
 
     The minput_toggle () function toggles the input method associated
-    with the input context $IC.  */
+    with input context $IC.  */
 /***ja
     @brief ÆþÎϥ᥽¥Ã¥É¤òÀÚÂؤ¨¤ë.
 
-    ´Ø¿ô minput_toggle () ¤ÏÆþÎÏ¥³¥ó¥Æ¥¯¥¹¥È $IC ¤ËÂбþÉÕ¤±¤é¤ì¤¿ÆþÎÏ
-    ¥á¥½¥Ã¥É¤ò¥È¥°¥ë¤¹¤ë¡£
+    ´Ø¿ô minput_toggle () ¤ÏÆþÎÏ¥³¥ó¥Æ¥¯¥¹¥È $IC 
+    ¤ËÂбþÉÕ¤±¤é¤ì¤¿ÆþÎϥ᥽¥Ã¥É¤ò¥È¥°¥ë¤¹¤ë¡£
     */
 
 void
@@ -2426,22 +2895,23 @@ minput_toggle (MInputContext *ic)
 /***en
     @brief Reset an input context.
 
-    The minput_reset_ic () function resets the input context $IC by
-    calling a callback functions corresponding to #Minput_reset.  It
-    actually shift the state to the initial one, and thus the current
+    The minput_reset_ic () function resets input context $IC by
+    calling a callback function corresponding to #Minput_reset.  It
+    actually shifts the state to the initial one, and thus the current
     preediting text (if any) is committed.  If necessary, a program
-    can extract the text by calling minput_lookup () just after the
-    call of minput_reset_ic ().  In that case, the arguments @c KEY
-    and @c ARG of minput_lookup are ignored..  */
+    can extract that committed text by calling minput_lookup () just
+    after the call of minput_reset_ic ().  In that case, the arguments
+    @c KEY and @c ARG of minput_lookup () are ignored.  */
 /***ja
     @brief ÆþÎÏ¥³¥ó¥Æ¥¯¥¹¥È¤ò¥ê¥»¥Ã¥È¤¹¤ë.
 
-    ´Ø¿ô minput_reset_ic () ¤Ï #Minput_reset ¤ËÂбþ¤¹¤ë¥³¡¼¥ë¥Ð¥Ã¥¯´Ø¿ô
-    ¤ò¸Æ¤Ö¤³¤È¤Ë¤è¤Ã¤ÆÆþÎÏ¥³¥ó¥Æ¥¯¥¹¥È $IC ¤ò¥ê¥»¥Ã¥È¤¹¤ë¡£¤³¤ì¤Ï¼ÂºÝ¤Ï
-    ÆþÎϥ᥽¥Ã¥É¤ò½é´ü¾õÂ֤˥·¥Õ¥È¤µ¤»¤ë¡£¤·¤¿¤¬¤Ã¤Æ¡¢¤â¤·¸½ºßÆþÎÏÃæ¤Î
-    ¥Æ¥­¥¹¥È¤¬¤¢¤ì¤Ð¡¢¤½¤ì¤Ï¥³¥ß¥Ã¥È¤µ¤ì¤ë¡£É¬Íפʤ饢¥×¥ê¥±¡¼¥·¥ç¥ó¥×
-    ¥í¥°¥é¥à¤Ï minput_lookup () ¤òÆɤó¤Ç¤½¤Î¥Æ¥­¥¹¥È¤ò¼è¤ê½Ð¤»¤ë¡£¤½¤Î
-    ºÝ¡¢minput_lookup () ¤Î°ú¿ô @c KEY ¤È @c ARG ¤Ï̵»ë¤µ¤ì¤ë¡£ */
+    ´Ø¿ô minput_reset_ic () ¤Ï #Minput_reset 
+    ¤ËÂбþ¤¹¤ë¥³¡¼¥ë¥Ð¥Ã¥¯´Ø¿ô¤ò¸Æ¤Ö¤³¤È¤Ë¤è¤Ã¤ÆÆþÎÏ¥³¥ó¥Æ¥¯¥¹¥È $IC 
+    ¤ò¥ê¥»¥Ã¥È¤¹¤ë¡£¥ê¥»¥Ã¥È¤È¤Ï¡¢¼ÂºÝ¤Ë¤ÏÆþÎϥ᥽¥Ã¥É¤ò½é´ü¾õÂ֤˰ܤ¹¤³¤È¤Ç¤¢¤ê¡¢¤·¤¿¤¬¤Ã¤Æ¡¢¤â¤·¸½ºßÆþÎÏÃæ¤Î¥Æ¥­¥¹¥È¤¬¤¢¤ì¤Ð¡¢¤½¤ì¤Ï¥³¥ß¥Ã¥È¤µ¤ì¤ë¡£
+    É¬Íפʤé¤Ð¡¢¥¢¥×¥ê¥±¡¼¥·¥ç¥ó¥×¥í¥°¥é¥à¤Ï minput_lookup () 
+    ¤òÆɤó¤Ç¤½¤Î¥³¥ß¥Ã¥È¤µ¤ì¤¿¥Æ¥­¥¹¥È¤ò¼è¤ê½Ð¤¹¤³¤È¤¬¤Ç¤­¡¢¤½¤ÎºÝ¡¢
+    minput_lookup () ¤Î°ú¿ô @c KEY ¤È @c ARG 
+    ¤Ï̵»ë¤µ¤ì¤ë¡£ */
 void
 minput_reset_ic (MInputContext *ic)
 {
@@ -2449,6 +2919,489 @@ minput_reset_ic (MInputContext *ic)
     minput__callback (ic, Minput_reset);
 }
 
+/*=*/
+/***en
+    @brief Key of a text property for detailed description.
+
+    The symbol #Mdetail_text is a managing key usually used for a
+    text property whose value is an M-text that contains detailed
+    description.  */
+/***ja
+    @brief ¾ÜºÙÀâÌÀÍѥƥ­¥¹¥È¥×¥í¥Ñ¥Æ¥£¤Î¥­¡¼.
+
+    ¥·¥ó¥Ü¥ë #Mdetail_text ¤Ï´ÉÍý¥­¡¼¤Ç¤¢¤ê¡¢Ä̾ï¾ÜºÙ¤ÊÀâÌÀ¤ò´Þ¤à 
+    M-text ¤òÃͤȤ·¤Æ»ý¤Ä¥Æ¥­¥¹¥È¥×¥í¥Ñ¥Æ¥£¤ËÍѤ¤¤é¤ì¤ë¡£
+    */
+MSymbol Mdetail_text;
+
+/***en
+    @brief Get description text of an input method.
+
+    The minput_get_description () function returns an M-text that
+    briefly describes the input method specified by $LANGUAGE and
+    $NAME.  The returned M-text may have a text property, from its
+    beginning to end, #Mdetail_text whose value is an M-text
+    describing the input method in more detail.
+
+    @return
+    If the specified input method has a description text, a pointer to
+    #MText is returned.  A caller have to free it by m17n_object_unref ().
+    If the input method does not have a description text, @c NULL is
+    returned.  */
+/***ja
+    @brief ÆþÎϥ᥽¥Ã¥É¤ÎÀâÌÀ¥Æ¥­¥¹¥È¤òÆÀ¤ë.
+
+    ´Ø¿ô minput_get_description () ¤Ï¡¢$LANGUAGE ¤È $NAME 
+    ¤Ë¤è¤Ã¤Æ»ØÄꤵ¤ì¤¿ÆþÎϥ᥽¥Ã¥É¤ò´Êñ¤ËÀâÌÀ¤¹¤ë M-text ¤òÊÖ¤¹¡£ÊÖ¤µ¤ì¤ë M-text 
+    ¤Ë¤Ï¡¢¤½¤ÎÁ´ÂΤËÂФ·¤Æ #Mdetail_text 
+    ¤È¤¤¤¦¥Æ¥­¥¹¥È¥×¥í¥Ñ¥Æ¥£¤¬Éղ䵤ì¤Æ¤¤¤ë¾ì¹ç¤¬¤¢¤ê¡¢¤½¤Î¥×¥í¥Ñ¥Æ¥£¤ÎÃͤÏÆþÎϥ᥽¥Ã¥É¤ò¤µ¤é¤Ë¾ÜºÙ¤ËÀâÌÀ¤¹¤ë
+    M-text ¤Ç¤¢¤ë¡£
+
+    @return 
+    »ØÄꤵ¤ì¤¿ÆþÎϥ᥽¥Ã¥É¤¬ÀâÌÀ¤¹¤ë¥Æ¥­¥¹¥È¤ò»ý¤Ã¤Æ¤¤¤ì¤Ð¡¢ 
+    #MText ¤Ø¤Î¥Ý¥¤¥ó¥¿¤òÊÖ¤¹¡£¸Æ¤Ó½Ð¤·Â¦¤Ï¡¢¤½¤ì¤ò m17n_object_unref
+    () ¤òÍѤ¤¤Æ²òÊü¤·¤Ê¤¯¤Æ¤Ï¤Ê¤é¤Ê¤¤¡£ÆþÎϥ᥽¥Ã¥É¤ËÀâÌÀ¥Æ¥­¥¹¥È¤¬Ìµ¤±¤ì¤Ð@c NULL ¤òÊÖ¤¹¡£ */
+
+MText *
+minput_get_description (MSymbol language, MSymbol name)
+{
+  MPlist *plist = load_im_info (language, name, M_description);
+  MPlist *pl;
+  MText *mt = NULL;
+
+  if (! plist)
+    return NULL;
+  if (! MPLIST_PLIST_P (plist))
+    {
+      M17N_OBJECT_UNREF (plist);      
+      return NULL;
+    }
+  pl = MPLIST_PLIST (plist);
+  while (! MPLIST_TAIL_P (pl) && ! MPLIST_MTEXT_P (pl))
+    pl = MPLIST_NEXT (pl);
+  if (MPLIST_MTEXT_P (pl))
+    mt = get_description_advance (pl);
+  M17N_OBJECT_UNREF (plist);
+  return mt;
+}
+
+/***en
+    @brief Get information about input method commands.
+
+    The minput_get_commands () function returns information about
+    input method commands of the input method specified by $LANGUAGE
+    and $NAME.  An input method command is a pseudo key event to which
+    one or more actual input key sequences are assigned.
+
+    There are two kinds of commands, global and local.  Global
+    commands are used by multiple input methods for the same purpose,
+    and have global key assignments.  Local commands are used only in
+    a specific input method, and have only local key assignments.
+
+    Each input method may locally change key assignments for global
+    commands.  A global key assignment for a global command are
+    effective only when the current input method does not have local
+    key assignments for that command.
+
+    If $NAME is #Mnil, information about global commands is returned.
+    In this case $LANGUAGE is ignored.
+
+    If $NAME is not #Mnil, information about those commands that have
+    local key assignments in the input method specified by $LANGUAGE
+    and $NAME is returned.
+
+    @return
+    If no input method commands are found, this function returns @c NULL.
+
+    Otherwise, a pointer to a plist is returned.  The key of each
+    element in the plist is a symbol representing a command, and the
+    value is a plist of the form COMMAND-INFO described below.
+
+    The first element of COMMAND-INFO has the key #Mtext, and the
+    value is an M-text describing the command briefly.  This M-text
+    may have a text property whose key is #Mdetail_text and whose
+    value is an M-text describing the command in more detail.
+
+    If there are no more elements, that means no key sequences are
+    assigned to the command.  Otherwise, each of the remaining
+    elements has the key #Mplist, and the value is a plist whose keys are
+    #Msymbol and values are symbols representing input keys, which are
+    currently assigned to the command.
+
+    As the returned plist is kept in the library, the caller must not
+    modify nor free it.  */
+/***ja
+    @brief ÆþÎϥ᥽¥Ã¥É¤Î¥³¥Þ¥ó¥É¤Ë´Ø¤¹¤ë¾ðÊó¤òÆÀ¤ë.
+
+    ´Ø¿ô minput_get_commands () ¤Ï¡¢ $LANGUAGE ¤È $NAME 
+    ¤Ë¤è¤Ã¤Æ»ØÄꤵ¤ì¤¿ÆþÎϥ᥽¥Ã¥É¤ÎÆþÎϥ᥽¥Ã¥É¥³¥Þ¥ó¥É¤Ë´Ø¤¹¤ë¾ðÊó¤òÊÖ¤¹¡£
+    ÆþÎϥ᥽¥Ã¥É¥³¥Þ¥ó¥É¤È¤Ï¡¢µ¿»÷¥­¡¼¥¤¥Ù¥ó¥È¤Ç¤¢¤ê¡¢¤½¤ì¤¾¤ì¤Ë£±¤Ä°Ê¾å¤Î¼ÂºÝ¤ÎÆþÎÏ¥­¡¼¥·¡¼¥¯¥¨¥ó¥¹¤¬³ä¤êÅö¤Æ¤é¤ì¤Æ¤¤¤ë¤â¤Î¤ò»Ø¤¹¡£
+
+    ¥³¥Þ¥ó¥É¤Ë¤Ï¥°¥í¡¼¥Ð¥ë¤È¥í¡¼¥«¥ë¤Î£²¼ïÎब¤¢¤ë¡£
+    ¥°¥í¡¼¥Ð¥ë¥³¥Þ¥ó¥É¤ÏÊ£¿ô¤ÎÆþÎϥ᥽¥Ã¥É¤Ë¤ª¤¤¤Æ¡¢Æ±¤¸ÌÜŪ¤Ç¡¢¥°¥í¡¼¥Ð¥ë¤Ê¥­¡¼³ä¤êÅö¤Æ¤ÇÍѤ¤¤é¤ì¤ë¡£
+    ¥í¡¼¥«¥ë¥³¥Þ¥ó¥É¤ÏÆÃÄê¤ÎÆþÎϥ᥽¥Ã¥É¤Ç¤Î¤ß¡¢¥í¡¼¥«¥ë¤Ê¥­¡¼³äÅö¤Ç»ÈÍѤµ¤ì¤ë¡£
+
+    ¸Ä¡¹¤ÎÆþÎϥ᥽¥Ã¥É¤Ï¥°¥í¡¼¥Ð¥ë¥³¥Þ¥ó¥É¤Î¥­¡¼³äÅö¤òÊѹ¹¤¹¤ë¤³¤È¤â¤Ç¤­¤ë¡£
+    ¥°¥í¡¼¥Ð¥ë¥³¥Þ¥ó¥ÉÍѤΥ°¥í¡¼¥Ð¥ë¥­¡¼³ä¤êÅö¤Æ¤Ï¡¢»ÈÍѤ¹¤ëÆþÎϥ᥽¥Ã¥É¤Ë¤ª¤¤¤Æ¤½¤Î¥³¥Þ¥ó¥ÉÍÑ¤Î¥í¡¼¥«¥ë¤Ê¥­¡¼³äÅö¤¬Â¸ºß¤·¤Ê¤¤¾ì¹ç¤Ë¤Î¤ßÍ­¸ú¤Ç¤¢¤ë¡£
+
+    $NAME ¤¬ #Mnil ¤Ç¤¢¤ì¤Ð¡¢¥°¥í¡¼¥Ð¥ë¥³¥Þ¥ó¥É¤Ë´Ø¤¹¤ë¾ðÊó¤òÊÖ¤¹¡£
+    ¤³¤Î¾ì¹ç¡¢$LANGUAGE ¤Ï̵»ë¤µ¤ì¤ë¡£
+
+    $NAME ¤¬ #Mnil ¤Ç¤Ê¤±¤ì¤Ð¡¢$LANGUAGE ¤È $NAME 
+    ¤Ë¤è¤Ã¤Æ»ØÄꤵ¤ì¤ëÆþÎϥ᥽¥Ã¥É¤ËÃÖ¤±¤ë¥í¡¼¥«¥ë¤Ê¥­¡¼³ä¤êÅö¤Æ¤ò»ý¤Ä¥³¥Þ¥ó¥É¤Ë´Ø¤¹¤ë¾ðÊó¤òÊÖ¤¹¡£
+
+    @return
+    ÆþÎϥ᥽¥Ã¥É¥³¥Þ¥ó¥É¤¬¸«¤Ä¤«¤é¤Ê¤±¤ì¤Ð¡¢¤³¤Î´Ø¿ô¤Ï @c NULL ¤òÊÖ¤¹¡£
+
+    ¤½¤¦¤Ç¤Ê¤±¤ì¤Ð¥×¥í¥Ñ¥Æ¥£¥ê¥¹¥È¤Ø¤Î¥Ý¥¤¥ó¥¿¤òÊÖ¤¹¡£
+    ¥ê¥¹¥È¤Î³ÆÍ×ÁǤΥ­¡¼¤Ï¸Ä¡¹¤Î¥³¥Þ¥ó¥É¤ò¼¨¤¹¥·¥ó¥Ü¥ë¤Ç¤¢¤ê¡¢Ãͤϲ¼µ­¤Î 
+    COMMAND-INFO ¤Î·Á¼°¤Î¥×¥í¥Ñ¥Æ¥£¥ê¥¹¥È¤Ç¤¢¤ë¡£
+
+    COMMAND-INFO ¤ÎÂè°ìÍ×ÁǤϥ­¡¼¤È¤·¤Æ #Mtext 
+    ¤ò¡¢ÃͤȤ·¤Æ¤½¤Î¥³¥Þ¥ó¥É¤ò´Êñ¤ËÀâÌÀ¤¹¤ë M-text ¤ò»ý¤Ä¡£¤³¤Î M-text 
+    ¤Ï¡¢#Mdetail_text 
+    ¤ò¥­¡¼¤È¤¹¤ë¥Æ¥­¥¹¥È¥×¥í¥Ñ¥Æ¥£¤ò»ý¤Ä¤³¤È¤¬¤Ç¤­¡¢¤½¤ÎÃͤϤ½¤Î¥³¥Þ¥ó¥É¤ò¤è¤ê¾ÜºÙ¤ËÀâÌÀ¤¹¤ë
+    M-text ¤Ç¤¢¤ë¡£
+
+    ¤½¤ì°Ê³°¤ÎÍ×ÁǤ¬Ìµ¤±¤ì¤Ð¡¢¤³¤Î¥³¥Þ¥ó¥É¤ËÂФ·¤Æ¥­¡¼¥·¡¼¥¯¥¨¥ó¥¹¤¬³ä¤êÅö¤Æ¤é¤ì¤Æ¤¤¤Ê¤¤¤³¤È¤ò°ÕÌ£¤¹¤ë¡£
+    ¤½¤¦¤Ç¤Ê¤±¤ì¤Ð¡¢»Ä¤ê¤Î³ÆÍ×ÁǤϥ­¡¼¤È¤·¤Æ#Mplist 
+    ¤ò¡¢ÃͤȤ·¤Æ¥×¥í¥Ñ¥Æ¥£¥ê¥¹¥È¤ò»ý¤Ä¡£
+    ¤³¤Î¥×¥í¥Ñ¥Æ¥£¥ê¥¹¥È¤Î¥­¡¼¤Ï #Msymbol 
+    ¤Ç¤¢¤ê¡¢Ãͤϸ½ºß¤½¤Î¥³¥Þ¥ó¥É¤Ë³ä¤êÅö¤Æ¤é¤ì¤Æ¤¤¤ëÆþÎÏ¥­¡¼¤òɽ¤¹¥·¥ó¥Ü¥ë¤Ç¤¢¤ë¡£
+
+    ÊÖ¤µ¤ì¤ë¥×¥í¥Ñ¥Æ¥£¥ê¥¹¥È¤Ï¥é¥¤¥Ö¥é¥ê¤Ë¤è¤Ã¤Æ´ÉÍý¤µ¤ì¤Æ¤ª¤ê¡¢¸Æ¤Ó½Ð¤·Â¦¤ÇÊѹ¹¤·¤¿¤ê²òÊü¤·¤¿¤ê¤·¤Æ¤Ï¤Ê¤é¤Ê¤¤¡£*/
+
+MPlist *
+minput_get_commands (MSymbol language, MSymbol name)
+{
+  MPlist *plist = get_command_list (language, name);
+
+  return (! plist || MPLIST_TAIL_P (plist) ? NULL : plist);
+}
+
+/***en
+    @brief Assign a key sequence to an input method command.
+
+    The minput_assign_command_keys () function assigns input key
+    sequence $KEYSEQ to input method command $COMMAND for the input
+    method specified by $LANGUAGE and $NAME.  If $NAME is #Mnil, the
+    key sequence is assigned globally no matter what $LANGUAGE is.
+    Otherwise the key sequence is assigned locally.
+
+    Each element of $KEYSEQ must have the key $Msymbol and the value
+    must be a symbol representing an input key.
+
+    $KEYSEQ may be @c NULL, in which case, all assignments are deleted
+    globally or locally.
+
+    This assignment gets effective in a newly opened input method.
+
+    @return
+    If the operation was successful, 0 is returned.  Otherwise -1 is
+    returned, and #merror_code is set to #MERROR_IM.  */
+/***ja
+    @brief ÆþÎϥ᥽¥Ã¥É¥³¥Þ¥ó¥É¤Ë¥­¡¼¥·¡¼¥¯¥¨¥ó¥¹¤ò³ä¤êÅö¤Æ¤ë.
+
+    ´Ø¿ô minput_assign_command_keys () ¤Ï¡¢ $LANGUAGE ¤È $NAME 
+    ¤Ë¤è¤Ã¤Æ»ØÄꤵ¤ì¤¿ÆþÎϥ᥽¥Ã¥ÉÍѤÎÆþÎϥ᥽¥Ã¥É¥³¥Þ¥ó¥É $COMMAND 
+    ¤ËÂФ·¤Æ¡¢ÆþÎÏ¥­¡¼¥·¡¼¥¯¥¨¥ó¥¹ $KEYSEQ ¤ò³ä¤êÅö¤Æ¤ë¡£ $NAME ¤¬ #Mnil
+    ¤Ê¤é¤Ð¡¢$LANGUAGE ¤Ë´Ø·¸¤Ê¤¯¡¢ÆþÎÏ¥­¡¼¥·¡¼¥¯¥¨¥ó¥¹¤Ï¥°¥í¡¼¥Ð¥ë¤Ë³ä¤êÅö¤Æ¤é¤ì¤ë¡£
+    ¤½¤¦¤Ç¤Ê¤ì¤Ð¡¢³ä¤êÅö¤Æ¤Ï¥í¡¼¥«¥ë¤Ç¤¢¤ë¡£
+
+    $KEYSEQ ¤Î³ÆÍ×ÁǤϥ­¡¼¤È¤·¤Æ $Msymbol 
+    ¤ò¡¢ÃͤȤ·¤ÆÆþÎÏ¥­¡¼¤òɽ¤¹¥·¥ó¥Ü¥ë¤ò»ý¤¿¤Ê¤¯¤Æ¤Ï¤Ê¤é¤Ê¤¤¡£
+
+    $KEYSEQ ¤Ï @c NULL ¤Ç¤â¤è¤¤¡£
+    ¤³¤Î¾ì¹ç¡¢¥°¥í¡¼¥Ð¥ë¤â¤·¤¯¤Ï¥í¡¼¥«¥ë¤Ê¤¹¤Ù¤Æ¤Î³ä¤êÅö¤Æ¤¬¾Ãµî¤µ¤ì¤ë¡£
+
+    ¤³¤Î³ä¤êÅö¤Æ¤Ï¡¢³ä¤êÅö¤Æ°Ê¹ß¿·¤·¤¯¥ª¡¼¥×¥ó¤µ¤ì¤¿ÆþÎϥ᥽¥Ã¥É¤«¤éÍ­¸ú¤Ë¤Ê¤ë¡£
+
+    @return 
+    ½èÍý¤¬À®¸ù¤¹¤ì¤Ð 0 ¤òÊÖ¤¹¡£¤½¤¦¤Ç¤Ê¤±¤ì¤Ð -1 ¤òÊÖ¤·¡¢
+    #merror_code ¤ò #MERROR_IM ¤ËÀßÄꤹ¤ë¡£  */
+
+int
+minput_assign_command_keys (MSymbol language, MSymbol name,
+                           MSymbol command, MPlist *keyseq)
+{
+  MPlist *plist, *pl, *p;
+
+  if (check_command_keyseq (keyseq) < 0
+      || ! (plist = get_command_list (language, name)))
+    MERROR (MERROR_IM, -1);
+  pl = mplist_get (plist, command);
+  if (pl)
+    {
+      pl = MPLIST_NEXT (pl);
+      if (! keyseq)
+       while ((p = mplist_pop (pl)))
+         M17N_OBJECT_UNREF (p);
+      else
+       {
+         keyseq = mplist_copy (keyseq);
+         mplist_push (pl, Mplist, keyseq);
+         M17N_OBJECT_UNREF (keyseq);
+       }
+    }
+  else
+    {
+      if (name == Mnil)
+       MERROR (MERROR_IM, -1);
+      if (! keyseq)
+       return 0;
+      pl = get_command_list (Mnil, Mnil); /* Get global commands.  */
+      pl = mplist_get (pl, command);
+      if (! pl)
+       MERROR (MERROR_IM, -1);
+      p = mplist ();
+      mplist_add (p, Mtext, mplist_value (pl));
+      keyseq = mplist_copy (keyseq);
+      mplist_add (p, Mplist, keyseq);
+      M17N_OBJECT_UNREF (keyseq);
+      mplist_push (plist, command, p);
+    }
+  return 0;
+}
+
+/***en
+    @brief Get a list of variables of an input method.
+
+    The minput_get_variables () function returns a plist (#MPlist) of
+    variables used to control the behavior of the input method
+    specified by $LANGUAGE and $NAME.  The key of an element of the
+    plist is a symbol representing a variable, and the value is a
+    plist of the form VAR-INFO (described below) that carries the
+    information about the variable.
+
+    The first element of VAR-INFO has the key #Mtext, and the value is
+    an M-text describing the variable briefly.  This M-text may have a
+    text property #Mdetail_text whose value is an M-text describing
+    the variable in more detail.
+
+    The second element of VAR-INFO is for the value of the variable.
+    The key is #Minteger, #Msymbol, or #Mtext, and the value is an
+    integer, a symbol, or an M-text, respectively.  The variable is
+    set to this value when an input context is created for the input
+    method.
+
+    If there are no more elements, the variable can take any value
+    that matches with the above type.  Otherwise, the remaining
+    elements of VAR-INFO are to specify valid values of the variable.
+
+    If the type of the variable is integer, the following elements
+    have the key #Minteger or #Mplist.  If it is #Minteger, the value
+    is a valid integer value.  If it is #Mplist, the value is a plist
+    of two of elements.  Both of them have the key #Minteger, and
+    values are the minimum and maximum bounds of the valid value
+    range.
+
+    If the type of the variable is symbol or M-text, the following
+    elements of the plist have the key #Msymbol or #Mtext,
+    respectively, and the value must be a valid one.
+
+    For instance, suppose an input method has the variables:
+
+    @li name:intvar, description: "value is an integer",
+         initial value:0, value-range:0..3,10,20
+
+    @li name:symvar, description: "value is a symbol",
+         initial value:nil, value-range:a, b, c, nil
+
+    @li name:txtvar, description: "value is an M-text",
+         initial value:empty text, no value-range (i.e. any text)
+
+    Then, the returned plist has this form ('X:Y' means X is a key and Y is
+    a value, and '(...)' means a plist):
+
+@verbatim
+    plist:(intvar:(mtext:'value is an integer'
+                   integer:0
+                  plist:(integer:0 integer:3)
+                   integer:10
+                   integer:20))
+           symvar:(mtext:"value is a symbol"
+                   symbol:nil
+                   symbol:a
+                   symbol:b
+                   symbol:c
+                   symbol:nil))
+           txtvar:(mtext:"value is an M-text"
+                   mtext:""))
+@endverbatim
+
+    @return
+    If the input method uses any variables, a pointer to #MPlist is
+    returned.  As the plist is kept in the library, a caller must not
+    modify nor free it.  If the input method does not use any
+    variable, @c NULL is returned.  */
+/***ja
+    @brief ÆþÎϥ᥽¥Ã¥É¤ÎÊÑ¿ô¥ê¥¹¥È¤òÆÀ¤ë.
+
+    ´Ø¿ô minput_get_variables () ¤Ï¡¢$LANGUAGE ¤È $NAME 
+    ¤Ë¤è¤Ã¤Æ»ØÄꤵ¤ì¤¿ÆþÎϥ᥽¥Ã¥É¤Î¿¶¤ëÉñ¤¤¤òÀ©¸æ¤¹¤ëÊÑ¿ô¤Î¥×¥í¥Ñ¥Æ¥£¥ê¥¹¥È 
+    (#MPlist) ¤òÊÖ¤¹¡£¥ê¥¹¥È¤Î³ÆÍ×ÁǤΥ­¡¼¤ÏÊÑ¿ô¤òɽ¤¹¥·¥ó¥Ü¥ë¤Ç¤¢¤ë¡£
+    ³ÆÍ×ÁǤÎÃͤϲ¼µ­¤Î VAR-INFO 
+    ¤Î·Á¼°¤Î¥×¥í¥Ñ¥Æ¥£¥ê¥¹¥È¤Ç¤¢¤ê¡¢³ÆÊÑ¿ô¤Ë´Ø¤¹¤ë¾ðÊó¤ò¼¨¤·¤Æ¤¤¤ë¡£
+
+    VAR-INFO ¤ÎÂè°ìÍ×ÁǤϥ­¡¼¤È¤·¤Æ #Mtext ¤ò¡¢ÃͤȤ·¤Æ¤½¤ÎÊÑ¿ô¤ò´Êñ¤ËÀâÌÀ¤¹¤ë
+    M-text ¤ò»ý¤Ä¡£¤³¤Î M-text ¤Ï¡¢#Mdetail_text 
+    ¤ò¥­¡¼¤È¤¹¤ë¥Æ¥­¥¹¥È¥×¥í¥Ñ¥Æ¥£¤ò»ý¤Ä¤³¤È¤¬¤Ç¤­¡¢¤½¤ÎÃͤϤ½¤ÎÊÑ¿ô¤ò¤è¤ê¾ÜºÙ¤ËÀâÌÀ¤¹¤ë
+    M-text ¤Ç¤¢¤ë¡£
+
+    VAR-INFO ¤ÎÂèÆóÍ×ÁǤÏÊÑ¿ô¤ÎÃͤò¼¨¤¹¡£¥­¡¼¤Ï #Minteger, #Msymbol,
+    #Mtext ¤Î¤¤¤º¤ì¤«¤Ç¤¢¤ê¡¢ÃͤϤ½¤ì¤¾¤ìÀ°¿ôÃÍ¡¢¥·¥ó¥Ü¥ë¡¢M-text  ¤Ç¤¢¤ë¡£
+    ¤³¤ÎÆþÎϥ᥽¥Ã¥ÉÍѤÎÆþÎÏ¥³¥ó¥Æ¥¹¥È¤¬ºî¤é¤ì¤ë»þÅÀ¤Ç¤Ï¡¢ÊÑ¿ô¤Ï¤³¤ÎÃͤËÀßÄꤵ¤ì¤Æ¤¤¤ë¡£
+
+    VAR-INFO ¤Ë¤½¤ì°Ê³°¤ÎÍ×ÁǤ¬Ìµ¤±¤ì¤Ð¡¢ÊÑ¿ô¤Ï¾åµ­¤Î·¿¤Ë¹çÃפ¹¤ë¸Â¤ê¤É¤Î¤è¤¦¤ÊÃͤò¤È¤ë¤³¤È¤â¤Ç¤­¤ë¡£
+    ¤½¤¦¤Ç¤Ê¤±¤ì¤Ð¡¢VAR-INFO ¤Î»Ä¤ê¤ÎÍ×ÁǤˤè¤Ã¤ÆÊÑ¿ô¤ÎÍ­¸ú¤ÊÃͤ¬»ØÄꤵ¤ì¤ë¡£
+
+    ÊÑ¿ô¤Î·¿¤¬À°¿ô¤Ç¤¢¤ì¤Ð¡¢¤½¤ì°Ê¹ß¤ÎÍ×ÁǤϠ#Minteger ¤« #Mplist 
+    ¤ò¥­¡¼¤È¤·¤Æ»ý¤Ä¡£ #Minteger ¤Ç¤¢¤ì¤Ð¡¢ÃͤÏÍ­¸ú¤ÊÃͤò¼¨¤¹À°¿ôÃͤǤ¢¤ë¡£
+    #Mplist ¤Ç¤¢¤ì¤Ð¡¢ÃͤÏÆó¤Ä¤ÎÍ×ÁǤò»ý¤Ä¥×¥í¥Ñ¥Æ¥£¥ê¥¹¥È¤Ç¤¢¤ê¡¢³ÆÍ×ÁǤϥ­¡¼¤È¤·¤Æ
+    #Minteger ¤ò¡¢ÃͤȤ·¤Æ¤½¤ì¤¾¤ìÍ­¸ú¤ÊÃͤξå¸ÂÃͤȲ¼¸ÂÃͤò¤È¤ë¡£
+
+    ÊÑ¿ô¤Î·¿¤¬¥·¥ó¥Ü¥ë¤« M-text ¤Ç¤¢¤ì¤Ð¡¢¤½¤ì°Ê¹ß¤ÎÍ×ÁǤϥ­¡¼¤È¤·¤Æ¤½¤ì¤¾¤ì
+    #Msymbol ¤« #Mtext ¤ò»ý¤Á¡¢ÃͤϤ½¤Î·¿¤Ë¹çÃפ¹¤ë¤â¤Î¤Ç¤¢¤ë¡£
+
+    Îã¤È¤·¤Æ¡¢¤¢¤ëÆþÎϥ᥽¥Ã¥É¤¬¼¡¤Î¤è¤¦¤ÊÊÑ¿ô¤ò»ý¤Ä¾ì¹ç¤ò¹Í¤¨¤è¤¦¡£
+
+    @li name:intvar, ÀâÌÀ:"value is an integer",
+        ½é´üÃÍ:0, ÃͤÎÈÏ°Ï:0..3,10,20
+
+    @li name:symvar, ÀâÌÀ:"value is a symbol",
+         ½é´üÃÍ:nil, ÃͤÎÈÏ°Ï:a, b, c, nil
+
+    @li name:txtvar, ÀâÌÀ:"value is an M-text",
+        ½é´üÃÍ:empty text, ÃͤÎÈϰϤʤ·(¤É¤ó¤Ê M-text ¤Ç¤â²Ä)
+
+    ¤³¤Î¾ì¹ç¡¢ÊÖ¤µ¤ì¤ë¥ê¥¹¥È¤Ï°Ê²¼¤Î¤è¤¦¤Ë¤Ê¤ë¡£¡Ê'X:Y' ¤È¤¤¤¦µ­Ë¡¤Ï X 
+    ¤¬¥­¡¼¤Ç Y ¤¬ÃͤǤ¢¤ë¤³¤È¤ò¡¢¤Þ¤¿ '(...)' ¤Ï¥×¥í¥Ñ¥Æ¥£¥ê¥¹¥È¤ò¼¨¤¹¡£¡Ë
+
+@verbatim
+    plist:(intvar:(mtext:"value is an integer"
+                   integer:0
+                  plist:(integer:0 integer:3)
+                   integer:10
+                   integer:20))
+           symvar:(mtext:"value is a symbol"
+                   symbol:nil
+                   symbol:a
+                   symbol:b
+                   symbol:c
+                   symbol:nil))
+           txtvar:(mtext:"value is an M-text"
+                   mtext:""))
+@endverbatim
+
+    @return 
+    ÆþÎϥ᥽¥Ã¥É¤¬²¿¤é¤«¤ÎÊÑ¿ô¤ò»ÈÍѤ·¤Æ¤¤¤ì¤Ð #MPlist ¤Ø¤ÎÊÑ¿ô¤òÊÖ¤¹¡£
+    ÊÖ¤µ¤ì¤ë¥×¥í¥Ñ¥Æ¥£¥ê¥¹¥È¤Ï¥é¥¤¥Ö¥é¥ê¤Ë¤è¤Ã¤Æ´ÉÍý¤µ¤ì¤Æ¤ª¤ê¡¢¸Æ¤Ó½Ð¤·Â¦¤ÇÊѹ¹¤·¤¿¤ê²òÊü¤·¤¿¤ê¤·¤Æ¤Ï¤Ê¤é¤Ê¤¤¡£
+    ÆþÎϥ᥽¥Ã¥É¤¬ÊÑ¿ô¤ò°ìÀÚ»ÈÍѤ·¤Æ¤Ê¤±¤ì¤Ð¡¢@c NULL ¤òÊÖ¤¹¡£  */
+
+MPlist *
+minput_get_variables (MSymbol language, MSymbol name)
+{
+  MPlist *plist = get_variable_list (language, name);
+
+  return (! plist || MPLIST_TAIL_P (plist) ? NULL : plist);
+}
+
+/***en
+    @brief Set the initial value of an input method variable.
+
+    The minput_set_variable () function sets the initial value of
+    input method variable $VARIABLE to $VALUE for the input method
+    specified by $LANGUAGE and $NAME.
+
+    By default, the initial value is 0.
+
+    This setting gets effective in a newly opened input method.
+
+    @return
+    If the operation was successful, 0 is returned.  Otherwise -1 is
+    returned, and #merror_code is set to #MERROR_IM.  */
+/***ja
+    @brief ÆþÎϥ᥽¥Ã¥ÉÊÑ¿ô¤Î½é´üÃͤòÀßÄꤹ¤ë.
+
+    ´Ø¿ô minput_set_variable () ¤Ï¡¢$LANGUAGE ¤È $NAME 
+    ¤Ë¤è¤Ã¤Æ»ØÄꤵ¤ì¤¿ÆþÎϥ᥽¥Ã¥É¤ÎÆþÎϥ᥽¥Ã¥ÉÊÑ¿ô $VARIABLE
+    ¤Î½é´üÃͤò¡¢ $VALUE ¤ËÀßÄꤹ¤ë¡£
+
+    ¥Ç¥Õ¥©¥ë¥È¤Î½é´üÃͤϠ0 ¤Ç¤¢¤ë¡£
+
+    ¤³¤ÎÀßÄê¤Ï¡¢¿·¤·¤¯¥ª¡¼¥×¥ó¤µ¤ì¤¿ÆþÎϥ᥽¥Ã¥É¤«¤éÍ­¸ú¤È¤Ê¤ë¡£
+
+    @return
+    ½èÍý¤¬À®¸ù¤¹¤ì¤Ð 0 ¤òÊÖ¤¹¡£¤½¤¦¤Ç¤Ê¤±¤ì¤Ð -1 ¤òÊÖ¤·¡¢
+    #merror_code ¤ò #MERROR_IM ¤ËÀßÄꤹ¤ë¡£  */
+
+int
+minput_set_variable (MSymbol language, MSymbol name,
+                    MSymbol variable, void *value)
+{
+  MPlist *plist, *val_element, *range_element;
+  MSymbol type;
+
+  if (language == Mnil || name == Mnil)
+    MERROR (MERROR_IM, -1);
+  plist = get_variable_list (language, name);
+  if (! plist)
+    MERROR (MERROR_IM, -1);
+  plist = (MPlist *) mplist_get (plist, variable);
+  if (! plist)
+    MERROR (MERROR_IM, -1);
+  val_element = MPLIST_NEXT (plist);
+  type = MPLIST_KEY (val_element);
+  range_element = MPLIST_NEXT (val_element);
+    
+  if (! MPLIST_TAIL_P (range_element))
+    {
+      if (type == Minteger)
+       {
+         int val = (int) value, this_val;
+      
+         MPLIST_DO (plist, range_element)
+           {
+             this_val = (int) MPLIST_VAL (plist);
+             if (MPLIST_PLIST_P (plist))
+               {
+                 int min_bound, max_bound;
+                 MPlist *pl = MPLIST_PLIST (plist);
+
+                 min_bound = (int) MPLIST_VAL (pl);
+                 pl = MPLIST_NEXT (pl);
+                 max_bound = (int) MPLIST_VAL (pl);
+                 if (val >= min_bound && val <= max_bound)
+                   break;
+               }
+             else if (val == this_val)
+               break;
+           }
+         if (MPLIST_TAIL_P (plist))
+           MERROR (MERROR_IM, -1);
+       }
+      else if (type == Msymbol)
+       {
+         MPLIST_DO (plist, range_element)
+           if (MPLIST_SYMBOL (plist) == (MSymbol) value)
+             break;
+         if (MPLIST_TAIL_P (plist))
+           MERROR (MERROR_IM, -1);
+       }
+      else                     /* type == Mtext */
+       {
+         MPLIST_DO (plist, range_element)
+           if (mtext_cmp (MPLIST_MTEXT (plist), (MText *) value) == 0)
+             break;
+         if (MPLIST_TAIL_P (plist))
+           MERROR (MERROR_IM, -1);
+         M17N_OBJECT_REF (value);
+       }
+    }
+
+  mplist_set (val_element, type, value);
+  return 0;
+}
 
 /*** @} */
 /*=*/
@@ -2469,8 +3422,8 @@ minput_reset_ic (MInputContext *ic)
 /***ja
     @brief ÆþÎϥ᥽¥Ã¥É¤ò¥À¥ó¥×¤¹¤ë.
 
-    ´Ø¿ô mdebug_dump_im () ¤ÏÆþÎϥ᥽¥Ã¥É $IM ¤ò stderr ¤Ë¿Í´Ö¤Ë²ÄÆɤÊ
-    ·Á¤Ç°õºþ¤¹¤ë¡£$INDENT ¤Ï£²¹ÔÌܰʹߤΥ¤¥ó¥Ç¥ó¥È¤ò»ØÄꤹ¤ë¡£
+    ´Ø¿ô mdebug_dump_im () ¤ÏÆþÎϥ᥽¥Ã¥É $IM ¤ò stderr 
+    ¤Ë¿Í´Ö¤Ë²ÄÆɤʷÁ¤Ç°õºþ¤¹¤ë¡£$INDENT ¤Ï£²¹ÔÌܰʹߤΥ¤¥ó¥Ç¥ó¥È¤ò»ØÄꤹ¤ë¡£
 
     @return
     ¤³¤Î´Ø¿ô¤Ï $IM ¤òÊÖ¤¹¡£  */